Skip to content

Commit 21624b8

Browse files
committedOct 18, 2018
[MERGE #5731 @yullin-ms] Implemented Math min and max as JsBuiltIns
Merge pull request #5731 from yullin-ms:mathMinMax Implemented Math min and max as JsBuiltIns
2 parents eeba684 + 6c42b34 commit 21624b8

17 files changed

+7405
-6469
lines changed
 

‎lib/Runtime/Base/JnDirectFields.h

+4
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,8 @@ ENTRY(Array_every)
659659
ENTRY(Array_includes)
660660
ENTRY(Array_reduce)
661661
ENTRY(Object_fromEntries)
662+
ENTRY(Math_min)
663+
ENTRY(Math_max)
662664
ENTRY(FunctionKind)
663665

664666
// EngineInterfaceObject built-ins
@@ -668,6 +670,8 @@ ENTRY(builtInJavascriptArrayEntryIndexOf)
668670
ENTRY(builtInJavascriptArrayEntrySome)
669671
ENTRY(builtInJavascriptArrayEntryEvery)
670672
ENTRY(builtInJavascriptArrayEntryIncludes)
673+
ENTRY(builtInMathMin)
674+
ENTRY(builtInMathMax)
671675
ENTRY(EngineInterface)
672676
ENTRY(builtInCallInstanceFunction)
673677

‎lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
44
//-------------------------------------------------------------------------------------------------------
55
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.
6-
// This file was generated with tools\update_bytecode_version.ps1
76

8-
// {9FAAF688-ACBA-4092-BA5B-77D97D3CD53A}
7+
// {D8913E7E-E430-4B28-81DD-EDD3EE5F263B}
98
const GUID byteCodeCacheReleaseFileVersion =
10-
{ 0x9FAAF688, 0xACBA, 0x4092, { 0xBA, 0x5B, 0x77, 0xD9, 0x7D, 0x3C, 0xD5, 0x3A } };
9+
{ 0xD8913E7E, 0xE430, 0x4B28, { 0x81, 0xDD, 0xED, 0xD3, 0xEE, 0x5F, 0x26, 0x3B } };

‎lib/Runtime/Language/AsmJsBuiltInNames.h

+11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
//-------------------------------------------------------------------------------------------------------
55

66
// Default all macros to nothing
7+
8+
#ifndef ASMJS_JSBUILTIN_MATH_FUNC_NAMES
9+
#define ASMJS_JSBUILTIN_MATH_FUNC_NAMES(propertyId, funcName)
10+
#endif
11+
712
#ifndef ASMJS_MATH_FUNC_NAMES
813
#define ASMJS_MATH_FUNC_NAMES(name, propertyName, funcInfo)
914
#endif
@@ -24,6 +29,11 @@
2429
#define ASMJS_TYPED_ARRAY_NAMES(name, propertyName) ASMJS_ARRAY_NAMES(name, propertyName)
2530
#endif
2631

32+
#ifdef ENABLE_JS_BUILTINS
33+
ASMJS_JSBUILTIN_MATH_FUNC_NAMES(Js::PropertyIds::min, Min )
34+
ASMJS_JSBUILTIN_MATH_FUNC_NAMES(Js::PropertyIds::max, Max )
35+
#endif
36+
2737
ASMJS_MATH_FUNC_NAMES(sin, sin, Math::EntryInfo::Sin )
2838
ASMJS_MATH_FUNC_NAMES(cos, cos, Math::EntryInfo::Cos )
2939
ASMJS_MATH_FUNC_NAMES(tan, tan, Math::EntryInfo::Tan )
@@ -66,6 +76,7 @@ ASMJS_TYPED_ARRAY_NAMES(Float64Array, Float64Array)
6676
ASMJS_ARRAY_NAMES(byteLength, byteLength)
6777

6878
// help the caller to undefine all the macros
79+
#undef ASMJS_JSBUILTIN_MATH_FUNC_NAMES
6980
#undef ASMJS_MATH_FUNC_NAMES
7081
#undef ASMJS_MATH_CONST_NAMES
7182
#undef ASMJS_MATH_DOUBLE_CONST_NAMES

‎lib/Runtime/Language/AsmJsLink.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,18 @@ namespace Js{
191191
bool ASMLink::CheckIsBuiltinFunction(ScriptContext* scriptContext, const Var object, PropertyId propertyId, const FunctionInfo& funcInfo)
192192
{
193193
Var mathFuncObj = JavascriptOperators::OP_GetProperty(object, propertyId, scriptContext);
194+
#ifdef ENABLE_JS_BUILTINS
195+
if (scriptContext->IsJsBuiltInEnabled())
196+
{
197+
switch (propertyId)
198+
{
199+
#define ASMJS_JSBUILTIN_MATH_FUNC_NAMES(propertyId, funcName) case propertyId: \
200+
return VarIs<JavascriptFunction>(mathFuncObj) && \
201+
VarTo<JavascriptFunction>(mathFuncObj) == scriptContext->GetLibrary()->GetMath##funcName##Function();
202+
#include "AsmJsBuiltInNames.h"
203+
}
204+
}
205+
#endif
194206
return VarIs<JavascriptFunction>(mathFuncObj) &&
195207
VarTo<JavascriptFunction>(mathFuncObj)->GetFunctionInfo()->GetOriginalEntryPoint() == funcInfo.GetOriginalEntryPoint();
196208
}

‎lib/Runtime/Library/EngineInterfaceObjectBuiltIns.h

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ GlobalBuiltInConstructor(Symbol)
5656

5757
GlobalMathBuiltIn(Abs)
5858
GlobalMathBuiltIn(Floor)
59-
GlobalMathBuiltIn(Max)
6059
GlobalMathBuiltIn(Pow)
6160

6261
GlobalBuiltIn(JavascriptObject, DefineProperty)

‎lib/Runtime/Library/InJavascript/Intl.js.bc.32b.h

+785-785
Large diffs are not rendered by default.

‎lib/Runtime/Library/InJavascript/Intl.js.bc.64b.h

+788-788
Large diffs are not rendered by default.

‎lib/Runtime/Library/InJavascript/Intl.js.nojit.bc.32b.h

+793-793
Large diffs are not rendered by default.

‎lib/Runtime/Library/InJavascript/Intl.js.nojit.bc.64b.h

+772-772
Large diffs are not rendered by default.

‎lib/Runtime/Library/JavascriptLibrary.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,6 @@ namespace Js
18761876

18771877
/* No inlining Array_Fill */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::fill, &JavascriptArray::EntryInfo::Fill, 1);
18781878
/* No inlining Array_CopyWithin */ library->AddFunctionToLibraryObject(arrayPrototype, PropertyIds::copyWithin, &JavascriptArray::EntryInfo::CopyWithin, 2);
1879-
18801879
DebugOnly(CheckRegisteredBuiltIns(builtinFuncs, scriptContext));
18811880

18821881
arrayPrototype->SetHasNoEnumerableProperties(true);
@@ -2860,6 +2859,18 @@ namespace Js
28602859

28612860
Field(JavascriptFunction*)* builtinFuncs = library->GetBuiltinFunctions();
28622861

2862+
#ifdef ENABLE_JS_BUILTINS
2863+
if (scriptContext->IsJsBuiltInEnabled())
2864+
{
2865+
library->EnsureBuiltInEngineIsReady();
2866+
}
2867+
else
2868+
#endif
2869+
{
2870+
builtinFuncs[BuiltinFunction::Math_Max] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::max, &Math::EntryInfo::Max, 2);
2871+
builtinFuncs[BuiltinFunction::Math_Min] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::min, &Math::EntryInfo::Min, 2);
2872+
}
2873+
28632874
builtinFuncs[BuiltinFunction::Math_Abs] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::abs, &Math::EntryInfo::Abs, 1);
28642875
builtinFuncs[BuiltinFunction::Math_Acos] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::acos, &Math::EntryInfo::Acos, 1);
28652876
builtinFuncs[BuiltinFunction::Math_Asin] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::asin, &Math::EntryInfo::Asin, 1);
@@ -2870,8 +2881,6 @@ namespace Js
28702881
builtinFuncs[BuiltinFunction::Math_Exp] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::exp, &Math::EntryInfo::Exp, 1);
28712882
builtinFuncs[BuiltinFunction::Math_Floor] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::floor, &Math::EntryInfo::Floor, 1);
28722883
builtinFuncs[BuiltinFunction::Math_Log] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::log, &Math::EntryInfo::Log, 1);
2873-
builtinFuncs[BuiltinFunction::Math_Max] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::max, &Math::EntryInfo::Max, 2);
2874-
builtinFuncs[BuiltinFunction::Math_Min] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::min, &Math::EntryInfo::Min, 2);
28752884
builtinFuncs[BuiltinFunction::Math_Pow] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::pow, &Math::EntryInfo::Pow, 2);
28762885
builtinFuncs[BuiltinFunction::Math_Random] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::random, &Math::EntryInfo::Random, 0);
28772886
builtinFuncs[BuiltinFunction::Math_Round] = library->AddFunctionToLibraryObject(mathObject, PropertyIds::round, &Math::EntryInfo::Round, 1);

‎lib/Runtime/Library/JavascriptLibraryBase.h

+8
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ namespace Js
340340
Field(JavascriptFunction*) getStackTrace;
341341
#ifdef EDIT_AND_CONTINUE
342342
Field(JavascriptFunction*) editSource;
343+
#endif
344+
Field(JavascriptFunction*) mathMin;
345+
Field(JavascriptFunction*) mathMax;
346+
347+
#ifdef ENABLE_JS_BUILTINS
348+
public:
349+
JavascriptFunction* GetMathMinFunction() const { return mathMin; }
350+
JavascriptFunction* GetMathMaxFunction() const { return mathMax; }
343351
#endif
344352
};
345353
}

‎lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js

+98
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
__chakraLibrary.raiseFunctionArgument_NeedFunction = platform.raiseFunctionArgument_NeedFunction;
3535
__chakraLibrary.functionBind = platform.builtInJavascriptFunctionEntryBind;
3636
__chakraLibrary.objectDefineProperty = _objectDefineProperty;
37+
__chakraLibrary.positiveInfinity = platform.POSITIVE_INFINITY;
38+
__chakraLibrary.negativeInfinity = platform.NEGATIVE_INFINITY;
3739

3840
_objectDefineProperty(__chakraLibrary.ArrayIterator.prototype, 'next',
3941
// Object's getter and setter can get overriden on the prototype, in that case while setting the value attributes, we will end up with TypeError
@@ -595,4 +597,100 @@
595597
}
596598
return o;
597599
});
600+
601+
platform.registerFunction(platform.FunctionKind.Math_min, function (value1, value2) {
602+
// #sec-math.min
603+
604+
// If no arguments are given, the result is positive infinity
605+
// If any value is NaN, the result is NaN.
606+
// The comparison of values to determine the smallest value is done using the Abstract Relational Comparison algorithm except that +0 is considered to be larger than -0.
607+
if (arguments.length === 0 ) {
608+
return __chakraLibrary.positiveInfinity;
609+
}
610+
611+
value1 = +value1;
612+
if (value1 !== value1) {
613+
return NaN;
614+
}
615+
616+
if (arguments.length === 1) {
617+
return value1;
618+
}
619+
620+
if (arguments.length === 2) {
621+
value2 = +value2;
622+
if (value2 !== value2) {
623+
return NaN;
624+
}
625+
if ((value1 < value2) || (value1 === value2 && value1 === 0 && 1/value1 < 1/value2)) { // checks for -0 and +0
626+
return value1;
627+
}
628+
else {
629+
return value2;
630+
}
631+
}
632+
633+
let min = value1;
634+
let nextVal;
635+
636+
for (let i = 1; i < arguments.length; i++) {
637+
nextVal = +arguments[i];
638+
if (nextVal !== nextVal) {
639+
return NaN;
640+
}
641+
else if ((min > nextVal) || (min === nextVal && min === 0 && 1/min > 1/nextVal)) { // checks for -0 and +0
642+
min = nextVal;
643+
}
644+
}
645+
646+
return min;
647+
});
648+
649+
platform.registerFunction(platform.FunctionKind.Math_max, function (value1, value2) {
650+
// #sec-math.max
651+
652+
// If no arguments are given, the result is negative infinity
653+
// If any value is NaN, the result is NaN.
654+
// The comparison of values to determine the largest value is done using the Abstract Relational Comparison algorithm except that +0 is considered to be larger than -0.
655+
if (arguments.length === 0) {
656+
return __chakraLibrary.negativeInfinity;
657+
}
658+
659+
value1 = +value1;
660+
if (value1 !== value1) {
661+
return NaN;
662+
}
663+
664+
if (arguments.length === 1) {
665+
return value1;
666+
}
667+
668+
if (arguments.length === 2) {
669+
value2 = +value2;
670+
if (value2 !== value2) {
671+
return NaN;
672+
}
673+
if ((value1 > value2) || (value1 === value2 && value1 === 0 && 1/value1 > 1/value2)) { // checks for -0 and +0
674+
return value1;
675+
}
676+
else {
677+
return value2;
678+
}
679+
}
680+
681+
let max = value1;
682+
let nextVal;
683+
684+
for (let i = 1; i < arguments.length; i++) {
685+
nextVal = +arguments[i];
686+
if (nextVal !== nextVal) {
687+
return NaN;
688+
}
689+
else if ((max < nextVal) || (max === nextVal && max === 0 && 1/max < 1/nextVal)) { // checks for -0 and +0
690+
max = nextVal;
691+
}
692+
}
693+
694+
return max;
695+
});
598696
});

‎lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.bc.32b.h

+1,055-859
Large diffs are not rendered by default.

‎lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.bc.64b.h

+1,055-859
Large diffs are not rendered by default.

‎lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.nojit.bc.32b.h

+984-792
Large diffs are not rendered by default.

‎lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.nojit.bc.64b.h

+984-792
Large diffs are not rendered by default.

‎lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.cpp

+42-22
Original file line numberDiff line numberDiff line change
@@ -40,28 +40,37 @@
4040
} \
4141

4242
#define FUNCTIONKIND_VALUES(VALUE) \
43-
VALUE(Array, values, false) \
44-
VALUE(Array, keys, false) \
45-
VALUE(Array, entries, false) \
46-
VALUE(Array, indexOf, false) \
47-
VALUE(Array, filter, false) \
48-
VALUE(Array, flat, false) \
49-
VALUE(Array, flatMap, false) \
50-
VALUE(Array, forEach, false) \
51-
VALUE(Array, some, false) \
52-
VALUE(Array, every, false) \
53-
VALUE(Array, includes, false) \
54-
VALUE(Array, reduce, false) \
55-
VALUE(Object, fromEntries, true)
43+
VALUE(Array, values, Prototype) \
44+
VALUE(Array, keys, Prototype) \
45+
VALUE(Array, entries, Prototype) \
46+
VALUE(Array, indexOf, Prototype) \
47+
VALUE(Array, filter, Prototype) \
48+
VALUE(Array, flat, Prototype) \
49+
VALUE(Array, flatMap, Prototype) \
50+
VALUE(Array, forEach, Prototype) \
51+
VALUE(Array, some, Prototype) \
52+
VALUE(Array, every, Prototype) \
53+
VALUE(Array, includes, Prototype) \
54+
VALUE(Array, reduce, Prototype) \
55+
VALUE(Object, fromEntries, Constructor) \
56+
VALUE(Math, max, Object) \
57+
VALUE(Math, min, Object)
5658

5759
enum class FunctionKind
5860
{
59-
#define VALUE(ClassName, methodName, isStatic) ClassName##_##methodName,
60-
FUNCTIONKIND_VALUES(VALUE)
61+
#define VALUE(ClassName, methodName, propertyType) ClassName##_##methodName,
62+
FUNCTIONKIND_VALUES(VALUE)
6163
#undef VALUE
6264
Max
6365
};
6466

67+
enum class IsPropertyTypeStatic : bool
68+
{
69+
Prototype = false,
70+
Constructor = true,
71+
Object = true
72+
};
73+
6574
namespace Js
6675
{
6776

@@ -198,7 +207,7 @@ namespace Js
198207

199208
bool JsBuiltInEngineInterfaceExtensionObject::InitializeJsBuiltInNativeInterfaces(DynamicObject * builtInNativeInterfaces, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
200209
{
201-
int initSlotCapacity = 4; // for register{ChakraLibrary}Function, FunctionKind, and GetIteratorPrototype
210+
int initSlotCapacity = 6; // for register{ChakraLibrary}Function, FunctionKind, POSITIVE_INFINITY, NEGATIVE_INFINITY, and GetIteratorPrototype
202211

203212
typeHandler->Convert(builtInNativeInterfaces, mode, initSlotCapacity);
204213

@@ -207,11 +216,13 @@ namespace Js
207216

208217
DynamicObject * functionKindObj = library->CreateObject();
209218

210-
#define VALUE(ClassName, methodName, isStatic) library->AddMember(functionKindObj, PropertyIds::ClassName##_##methodName, JavascriptNumber::ToVar((int)FunctionKind::ClassName##_##methodName, scriptContext));
219+
#define VALUE(ClassName, methodName, propertyType) library->AddMember(functionKindObj, PropertyIds::ClassName##_##methodName, JavascriptNumber::ToVar((int)FunctionKind::ClassName##_##methodName, scriptContext));
211220
FUNCTIONKIND_VALUES(VALUE)
212221
#undef VALUE
213222

214223
library->AddMember(builtInNativeInterfaces, PropertyIds::FunctionKind, functionKindObj);
224+
library->AddMember(builtInNativeInterfaces, PropertyIds::POSITIVE_INFINITY, library->GetPositiveInfinite());
225+
library->AddMember(builtInNativeInterfaces, PropertyIds::NEGATIVE_INFINITY, library->GetNegativeInfinite());
215226

216227
library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerChakraLibraryFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterChakraLibraryFunction, 2);
217228
library->AddFunctionToLibraryObject(builtInNativeInterfaces, Js::PropertyIds::registerFunction, &JsBuiltInEngineInterfaceExtensionObject::EntryInfo::JsBuiltIn_RegisterFunction, 2);
@@ -297,12 +308,14 @@ namespace Js
297308
PropertyId methodPropID = PropertyIds::_none;
298309
PropertyString *methodPropString = nullptr;
299310
PropertyString *classPropString = nullptr;
311+
JavascriptString *fullName = nullptr;
312+
JavascriptString *dot = library->GetDotString();
300313
switch (funcKind)
301314
{
302-
#define VALUE(ClassName, methodName, _isStatic) \
315+
#define VALUE(ClassName, methodName, propertyType) \
303316
case FunctionKind::ClassName##_##methodName: \
304-
isStatic = _isStatic; \
305-
installTarget = _isStatic ? library->Get##ClassName##Constructor() : library->Get##ClassName##Prototype(); \
317+
isStatic = static_cast<bool>(IsPropertyTypeStatic::##propertyType); \
318+
installTarget = library->Get##ClassName##propertyType##(); \
306319
methodPropID = PropertyIds::methodName; \
307320
methodPropString = scriptContext->GetPropertyString(methodPropID); \
308321
classPropString = scriptContext->GetPropertyString(PropertyIds::ClassName); \
@@ -312,10 +325,9 @@ FUNCTIONKIND_VALUES(VALUE)
312325
default:
313326
AssertOrFailFastMsg(false, "funcKind should never be outside the range of projected values");
314327
}
328+
315329
Assert(methodPropString && classPropString && installTarget && methodPropID != PropertyIds::_none);
316330

317-
JavascriptString *fullName = nullptr;
318-
JavascriptString *dot = library->GetDotString();
319331
if (isStatic)
320332
{
321333
fullName = JavascriptString::Concat3(classPropString, dot, methodPropString);
@@ -370,6 +382,14 @@ FUNCTIONKIND_VALUES(VALUE)
370382
case FunctionKind::Array_reduce:
371383
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInJavascriptArrayEntryReduce, func);
372384
break;
385+
case FunctionKind::Math_max:
386+
library->mathMax = func;
387+
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMax, func);
388+
break;
389+
case FunctionKind::Math_min:
390+
library->mathMin = func;
391+
library->AddMember(scriptContext->GetLibrary()->GetEngineInterfaceObject()->GetCommonNativeInterfaces(), PropertyIds::builtInMathMin, func);
392+
break;
373393
// FunctionKinds with no entry functions
374394
case FunctionKind::Array_flat:
375395
case FunctionKind::Array_flatMap:

0 commit comments

Comments
 (0)
Please sign in to comment.