Reland: Use simple/fast inline function version of MinMax in JS
Use the simple inline function version of {Min, Max} where possible to improve performance Now uses an forced inline js function instead of a python macro to avoid expressions be evaluated twice Follow-up to CR: https://codereview.chromium.org/1331993004 Review URL: https://codereview.chromium.org/1410473002 Cr-Commit-Position: refs/heads/master@{#31411}
This commit is contained in:
parent
81ee94b650
commit
b00371b423
@ -16,7 +16,7 @@ var FLAG_harmony_tolength;
|
|||||||
var GlobalArray = global.Array;
|
var GlobalArray = global.Array;
|
||||||
var InternalArray = utils.InternalArray;
|
var InternalArray = utils.InternalArray;
|
||||||
var InternalPackedArray = utils.InternalPackedArray;
|
var InternalPackedArray = utils.InternalPackedArray;
|
||||||
var MathMin;
|
var MinSimple;
|
||||||
var ObjectHasOwnProperty;
|
var ObjectHasOwnProperty;
|
||||||
var ObjectIsFrozen;
|
var ObjectIsFrozen;
|
||||||
var ObjectIsSealed;
|
var ObjectIsSealed;
|
||||||
@ -28,7 +28,7 @@ var unscopablesSymbol = utils.ImportNow("unscopables_symbol");
|
|||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
Delete = from.Delete;
|
Delete = from.Delete;
|
||||||
MathMin = from.MathMin;
|
MinSimple = from.MinSimple;
|
||||||
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
||||||
ObjectIsFrozen = from.ObjectIsFrozen;
|
ObjectIsFrozen = from.ObjectIsFrozen;
|
||||||
ObjectIsSealed = from.ObjectIsSealed;
|
ObjectIsSealed = from.ObjectIsSealed;
|
||||||
@ -271,7 +271,7 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
|
|||||||
// Move data to new array.
|
// Move data to new array.
|
||||||
var new_array = new InternalArray(
|
var new_array = new InternalArray(
|
||||||
// Clamp array length to 2^32-1 to avoid early RangeError.
|
// Clamp array length to 2^32-1 to avoid early RangeError.
|
||||||
MathMin(len - del_count + num_additional_args, 0xffffffff));
|
MinSimple(len - del_count + num_additional_args, 0xffffffff));
|
||||||
var big_indices;
|
var big_indices;
|
||||||
var indices = %GetArrayKeys(array, len);
|
var indices = %GetArrayKeys(array, len);
|
||||||
if (IS_NUMBER(indices)) {
|
if (IS_NUMBER(indices)) {
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
|
|
||||||
var GlobalArrayBuffer = global.ArrayBuffer;
|
var GlobalArrayBuffer = global.ArrayBuffer;
|
||||||
var GlobalObject = global.Object;
|
var GlobalObject = global.Object;
|
||||||
var MathMax;
|
var MaxSimple;
|
||||||
var MathMin;
|
var MinSimple;
|
||||||
var ToPositiveInteger;
|
var ToPositiveInteger;
|
||||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
MathMax = from.MathMax;
|
MaxSimple = from.MaxSimple;
|
||||||
MathMin = from.MathMin;
|
MinSimple = from.MinSimple;
|
||||||
ToPositiveInteger = from.ToPositiveInteger;
|
ToPositiveInteger = from.ToPositiveInteger;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,16 +57,16 @@ function ArrayBufferSlice(start, end) {
|
|||||||
var first;
|
var first;
|
||||||
var byte_length = %_ArrayBufferGetByteLength(this);
|
var byte_length = %_ArrayBufferGetByteLength(this);
|
||||||
if (relativeStart < 0) {
|
if (relativeStart < 0) {
|
||||||
first = MathMax(byte_length + relativeStart, 0);
|
first = MaxSimple(byte_length + relativeStart, 0);
|
||||||
} else {
|
} else {
|
||||||
first = MathMin(relativeStart, byte_length);
|
first = MinSimple(relativeStart, byte_length);
|
||||||
}
|
}
|
||||||
var relativeEnd = IS_UNDEFINED(end) ? byte_length : end;
|
var relativeEnd = IS_UNDEFINED(end) ? byte_length : end;
|
||||||
var fin;
|
var fin;
|
||||||
if (relativeEnd < 0) {
|
if (relativeEnd < 0) {
|
||||||
fin = MathMax(byte_length + relativeEnd, 0);
|
fin = MaxSimple(byte_length + relativeEnd, 0);
|
||||||
} else {
|
} else {
|
||||||
fin = MathMin(relativeEnd, byte_length);
|
fin = MinSimple(relativeEnd, byte_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fin < first) {
|
if (fin < first) {
|
||||||
|
@ -16,8 +16,8 @@ var GetIterator;
|
|||||||
var GetMethod;
|
var GetMethod;
|
||||||
var GlobalArray = global.Array;
|
var GlobalArray = global.Array;
|
||||||
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
||||||
var MathMax;
|
var MaxSimple;
|
||||||
var MathMin;
|
var MinSimple;
|
||||||
var ObjectIsFrozen;
|
var ObjectIsFrozen;
|
||||||
var ObjectDefineProperty;
|
var ObjectDefineProperty;
|
||||||
|
|
||||||
@ -25,8 +25,8 @@ utils.Import(function(from) {
|
|||||||
FLAG_harmony_tolength = from.FLAG_harmony_tolength;
|
FLAG_harmony_tolength = from.FLAG_harmony_tolength;
|
||||||
GetIterator = from.GetIterator;
|
GetIterator = from.GetIterator;
|
||||||
GetMethod = from.GetMethod;
|
GetMethod = from.GetMethod;
|
||||||
MathMax = from.MathMax;
|
MaxSimple = from.MaxSimple;
|
||||||
MathMin = from.MathMin;
|
MinSimple = from.MinSimple;
|
||||||
ObjectIsFrozen = from.ObjectIsFrozen;
|
ObjectIsFrozen = from.ObjectIsFrozen;
|
||||||
ObjectDefineProperty = from.ObjectDefineProperty;
|
ObjectDefineProperty = from.ObjectDefineProperty;
|
||||||
});
|
});
|
||||||
@ -37,28 +37,28 @@ function InnerArrayCopyWithin(target, start, end, array, length) {
|
|||||||
target = TO_INTEGER(target);
|
target = TO_INTEGER(target);
|
||||||
var to;
|
var to;
|
||||||
if (target < 0) {
|
if (target < 0) {
|
||||||
to = MathMax(length + target, 0);
|
to = MaxSimple(length + target, 0);
|
||||||
} else {
|
} else {
|
||||||
to = MathMin(target, length);
|
to = MinSimple(target, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = TO_INTEGER(start);
|
start = TO_INTEGER(start);
|
||||||
var from;
|
var from;
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
from = MathMax(length + start, 0);
|
from = MaxSimple(length + start, 0);
|
||||||
} else {
|
} else {
|
||||||
from = MathMin(start, length);
|
from = MinSimple(start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
|
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
|
||||||
var final;
|
var final;
|
||||||
if (end < 0) {
|
if (end < 0) {
|
||||||
final = MathMax(length + end, 0);
|
final = MaxSimple(length + end, 0);
|
||||||
} else {
|
} else {
|
||||||
final = MathMin(end, length);
|
final = MinSimple(end, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = MathMin(final - from, length - to);
|
var count = MinSimple(final - from, length - to);
|
||||||
var direction = 1;
|
var direction = 1;
|
||||||
if (from < to && to < (from + count)) {
|
if (from < to && to < (from + count)) {
|
||||||
direction = -1;
|
direction = -1;
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
// Imports
|
// Imports
|
||||||
|
|
||||||
var GlobalObject = global.Object;
|
var GlobalObject = global.Object;
|
||||||
var MathMax;
|
var MaxSimple;
|
||||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
MathMax = from.MathMax;
|
MaxSimple = from.MaxSimple;
|
||||||
});
|
});
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -146,7 +146,7 @@ function AtomicsFutexWaitJS(ia, index, value, timeout) {
|
|||||||
if (NUMBER_IS_NAN(timeout)) {
|
if (NUMBER_IS_NAN(timeout)) {
|
||||||
timeout = INFINITY;
|
timeout = INFINITY;
|
||||||
} else {
|
} else {
|
||||||
timeout = MathMax(0, timeout);
|
timeout = MaxSimple(0, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return %AtomicsFutexWait(ia, index, value, timeout);
|
return %AtomicsFutexWait(ia, index, value, timeout);
|
||||||
@ -158,14 +158,14 @@ function AtomicsFutexWakeJS(ia, index, count) {
|
|||||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||||
return UNDEFINED;
|
return UNDEFINED;
|
||||||
}
|
}
|
||||||
count = MathMax(0, TO_INTEGER(count));
|
count = MaxSimple(0, TO_INTEGER(count));
|
||||||
return %AtomicsFutexWake(ia, index, count);
|
return %AtomicsFutexWake(ia, index, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
|
function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
|
||||||
CheckSharedInteger32TypedArray(ia);
|
CheckSharedInteger32TypedArray(ia);
|
||||||
index1 = TO_INTEGER(index1);
|
index1 = TO_INTEGER(index1);
|
||||||
count = MathMax(0, TO_INTEGER(count));
|
count = MaxSimple(0, TO_INTEGER(count));
|
||||||
value = TO_INT32(value);
|
value = TO_INT32(value);
|
||||||
index2 = TO_INTEGER(index2);
|
index2 = TO_INTEGER(index2);
|
||||||
if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
|
if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
|
||||||
|
@ -48,8 +48,8 @@ var InnerArraySome;
|
|||||||
var InnerArraySort;
|
var InnerArraySort;
|
||||||
var InnerArrayToLocaleString;
|
var InnerArrayToLocaleString;
|
||||||
var IsNaN;
|
var IsNaN;
|
||||||
var MathMax;
|
var MaxSimple;
|
||||||
var MathMin;
|
var MinSimple;
|
||||||
var PackedArrayReverse;
|
var PackedArrayReverse;
|
||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
@ -72,8 +72,8 @@ utils.Import(function(from) {
|
|||||||
InnerArraySort = from.InnerArraySort;
|
InnerArraySort = from.InnerArraySort;
|
||||||
InnerArrayToLocaleString = from.InnerArrayToLocaleString;
|
InnerArrayToLocaleString = from.InnerArrayToLocaleString;
|
||||||
IsNaN = from.IsNaN;
|
IsNaN = from.IsNaN;
|
||||||
MathMax = from.MathMax;
|
MaxSimple = from.MaxSimple;
|
||||||
MathMin = from.MathMin;
|
MinSimple = from.MinSimple;
|
||||||
PackedArrayReverse = from.PackedArrayReverse;
|
PackedArrayReverse = from.PackedArrayReverse;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -319,9 +319,9 @@ function TypedArraySlice(start, end) {
|
|||||||
|
|
||||||
var k;
|
var k;
|
||||||
if (relativeStart < 0) {
|
if (relativeStart < 0) {
|
||||||
k = MathMax(len + relativeStart, 0);
|
k = MaxSimple(len + relativeStart, 0);
|
||||||
} else {
|
} else {
|
||||||
k = MathMin(relativeStart, len);
|
k = MinSimple(relativeStart, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
var relativeEnd;
|
var relativeEnd;
|
||||||
@ -333,12 +333,12 @@ function TypedArraySlice(start, end) {
|
|||||||
|
|
||||||
var final;
|
var final;
|
||||||
if (relativeEnd < 0) {
|
if (relativeEnd < 0) {
|
||||||
final = MathMax(len + relativeEnd, 0);
|
final = MaxSimple(len + relativeEnd, 0);
|
||||||
} else {
|
} else {
|
||||||
final = MathMin(relativeEnd, len);
|
final = MinSimple(relativeEnd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = MathMax(final - k, 0);
|
var count = MaxSimple(final - k, 0);
|
||||||
var array = ConstructTypedArrayLike(this, count);
|
var array = ConstructTypedArrayLike(this, count);
|
||||||
// The code below is the 'then' branch; the 'else' branch species
|
// The code below is the 'then' branch; the 'else' branch species
|
||||||
// a memcpy. Because V8 doesn't canonicalize NaN, the difference is
|
// a memcpy. Because V8 doesn't canonicalize NaN, the difference is
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
|
|
||||||
var GlobalJSON = global.JSON;
|
var GlobalJSON = global.JSON;
|
||||||
var InternalArray = utils.InternalArray;
|
var InternalArray = utils.InternalArray;
|
||||||
var MathMax;
|
var MaxSimple;
|
||||||
var MathMin;
|
var MinSimple;
|
||||||
var ObjectHasOwnProperty;
|
var ObjectHasOwnProperty;
|
||||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
MathMax = from.MathMax;
|
MaxSimple = from.MaxSimple;
|
||||||
MathMin = from.MathMin;
|
MinSimple = from.MinSimple;
|
||||||
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ function JSONStringify(value, replacer, space) {
|
|||||||
}
|
}
|
||||||
var gap;
|
var gap;
|
||||||
if (IS_NUMBER(space)) {
|
if (IS_NUMBER(space)) {
|
||||||
space = MathMax(0, MathMin(TO_INTEGER(space), 10));
|
space = MaxSimple(0, MinSimple(TO_INTEGER(space), 10));
|
||||||
gap = %_SubString(" ", 0, space);
|
gap = %_SubString(" ", 0, space);
|
||||||
} else if (IS_STRING(space)) {
|
} else if (IS_STRING(space)) {
|
||||||
if (space.length > 10) {
|
if (space.length > 10) {
|
||||||
|
@ -159,8 +159,6 @@ macro TO_NAME(arg) = (%_ToName(arg));
|
|||||||
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
|
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
|
||||||
macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
|
macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
|
||||||
macro HAS_INDEX(array, index, is_array) = ((is_array && %_HasFastPackedElements(%IS_VAR(array))) ? (index < array.length) : (index in array));
|
macro HAS_INDEX(array, index, is_array) = ((is_array && %_HasFastPackedElements(%IS_VAR(array))) ? (index < array.length) : (index in array));
|
||||||
macro MAX_SIMPLE(argA, argB) = (argA < argB ? argB : argA);
|
|
||||||
macro MIN_SIMPLE(argA, argB) = (argA < argB ? argA : argB);
|
|
||||||
|
|
||||||
# Private names.
|
# Private names.
|
||||||
macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
|
macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
|
||||||
|
@ -186,6 +186,8 @@ function PostNatives(utils) {
|
|||||||
"MapIteratorNext",
|
"MapIteratorNext",
|
||||||
"MathMax",
|
"MathMax",
|
||||||
"MathMin",
|
"MathMin",
|
||||||
|
"MaxSimple",
|
||||||
|
"MinSimple",
|
||||||
"ObjectIsFrozen",
|
"ObjectIsFrozen",
|
||||||
"ObjectDefineProperty",
|
"ObjectDefineProperty",
|
||||||
"ObserveArrayMethods",
|
"ObserveArrayMethods",
|
||||||
|
@ -216,6 +216,20 @@ function ToPositiveInteger(x, rangeErrorIndex) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function MaxSimple(a, b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function MinSimple(a, b) {
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
%SetForceInlineFlag(MaxSimple);
|
||||||
|
%SetForceInlineFlag(MinSimple);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
// NOTE: Setting the prototype for Array must take place as early as
|
// NOTE: Setting the prototype for Array must take place as early as
|
||||||
@ -229,9 +243,11 @@ function ToPositiveInteger(x, rangeErrorIndex) {
|
|||||||
// Exports
|
// Exports
|
||||||
|
|
||||||
utils.Export(function(to) {
|
utils.Export(function(to) {
|
||||||
to.ToPositiveInteger = ToPositiveInteger;
|
to.MaxSimple = MaxSimple;
|
||||||
|
to.MinSimple = MinSimple;
|
||||||
to.SameValue = SameValue;
|
to.SameValue = SameValue;
|
||||||
to.SameValueZero = SameValueZero;
|
to.SameValueZero = SameValueZero;
|
||||||
|
to.ToPositiveInteger = ToPositiveInteger;
|
||||||
});
|
});
|
||||||
|
|
||||||
%InstallToContext([
|
%InstallToContext([
|
||||||
|
@ -18,6 +18,8 @@ var GlobalDataView = global.DataView;
|
|||||||
var GlobalObject = global.Object;
|
var GlobalObject = global.Object;
|
||||||
var InternalArray = utils.InternalArray;
|
var InternalArray = utils.InternalArray;
|
||||||
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
||||||
|
var MaxSimple;
|
||||||
|
var MinSimple;
|
||||||
var ToPositiveInteger;
|
var ToPositiveInteger;
|
||||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||||
|
|
||||||
@ -42,6 +44,8 @@ TYPED_ARRAYS(DECLARE_GLOBALS)
|
|||||||
|
|
||||||
utils.Import(function(from) {
|
utils.Import(function(from) {
|
||||||
ArrayValues = from.ArrayValues;
|
ArrayValues = from.ArrayValues;
|
||||||
|
MaxSimple = from.MaxSimple;
|
||||||
|
MinSimple = from.MinSimple;
|
||||||
ToPositiveInteger = from.ToPositiveInteger;
|
ToPositiveInteger = from.ToPositiveInteger;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,15 +217,15 @@ function NAMESubArray(begin, end) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (beginInt < 0) {
|
if (beginInt < 0) {
|
||||||
beginInt = MAX_SIMPLE(0, srcLength + beginInt);
|
beginInt = MaxSimple(0, srcLength + beginInt);
|
||||||
} else {
|
} else {
|
||||||
beginInt = MIN_SIMPLE(beginInt, srcLength);
|
beginInt = MinSimple(beginInt, srcLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endInt < 0) {
|
if (endInt < 0) {
|
||||||
endInt = MAX_SIMPLE(0, srcLength + endInt);
|
endInt = MaxSimple(0, srcLength + endInt);
|
||||||
} else {
|
} else {
|
||||||
endInt = MIN_SIMPLE(endInt, srcLength);
|
endInt = MinSimple(endInt, srcLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endInt < beginInt) {
|
if (endInt < beginInt) {
|
||||||
|
27
test/mjsunit/minmax-simple.js
Normal file
27
test/mjsunit/minmax-simple.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// Flags: --expose-natives-as natives
|
||||||
|
// Test the MaxSimple and MinSimple internal methods in runtime.js
|
||||||
|
|
||||||
|
var MaxSimple = natives.ImportNow("MaxSimple");
|
||||||
|
var MinSimple = natives.ImportNow("MinSimple");
|
||||||
|
|
||||||
|
function checkEvaluations(target) {
|
||||||
|
var evaluations = 0;
|
||||||
|
var observedNumber = {
|
||||||
|
valueOf: function() {
|
||||||
|
evaluations++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
target(observedNumber, observedNumber);
|
||||||
|
return evaluations;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(1, MaxSimple(-1, 1));
|
||||||
|
assertEquals(2, checkEvaluations(MaxSimple));
|
||||||
|
|
||||||
|
assertEquals(-1, MinSimple(-1, 1));
|
||||||
|
assertEquals(2, checkEvaluations(MinSimple));
|
Loading…
Reference in New Issue
Block a user