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 InternalArray = utils.InternalArray;
|
||||
var InternalPackedArray = utils.InternalPackedArray;
|
||||
var MathMin;
|
||||
var MinSimple;
|
||||
var ObjectHasOwnProperty;
|
||||
var ObjectIsFrozen;
|
||||
var ObjectIsSealed;
|
||||
@ -28,7 +28,7 @@ var unscopablesSymbol = utils.ImportNow("unscopables_symbol");
|
||||
|
||||
utils.Import(function(from) {
|
||||
Delete = from.Delete;
|
||||
MathMin = from.MathMin;
|
||||
MinSimple = from.MinSimple;
|
||||
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
||||
ObjectIsFrozen = from.ObjectIsFrozen;
|
||||
ObjectIsSealed = from.ObjectIsSealed;
|
||||
@ -271,7 +271,7 @@ function SparseMove(array, start_i, del_count, len, num_additional_args) {
|
||||
// Move data to new array.
|
||||
var new_array = new InternalArray(
|
||||
// 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 indices = %GetArrayKeys(array, len);
|
||||
if (IS_NUMBER(indices)) {
|
||||
|
@ -13,14 +13,14 @@
|
||||
|
||||
var GlobalArrayBuffer = global.ArrayBuffer;
|
||||
var GlobalObject = global.Object;
|
||||
var MathMax;
|
||||
var MathMin;
|
||||
var MaxSimple;
|
||||
var MinSimple;
|
||||
var ToPositiveInteger;
|
||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||
|
||||
utils.Import(function(from) {
|
||||
MathMax = from.MathMax;
|
||||
MathMin = from.MathMin;
|
||||
MaxSimple = from.MaxSimple;
|
||||
MinSimple = from.MinSimple;
|
||||
ToPositiveInteger = from.ToPositiveInteger;
|
||||
});
|
||||
|
||||
@ -57,16 +57,16 @@ function ArrayBufferSlice(start, end) {
|
||||
var first;
|
||||
var byte_length = %_ArrayBufferGetByteLength(this);
|
||||
if (relativeStart < 0) {
|
||||
first = MathMax(byte_length + relativeStart, 0);
|
||||
first = MaxSimple(byte_length + relativeStart, 0);
|
||||
} else {
|
||||
first = MathMin(relativeStart, byte_length);
|
||||
first = MinSimple(relativeStart, byte_length);
|
||||
}
|
||||
var relativeEnd = IS_UNDEFINED(end) ? byte_length : end;
|
||||
var fin;
|
||||
if (relativeEnd < 0) {
|
||||
fin = MathMax(byte_length + relativeEnd, 0);
|
||||
fin = MaxSimple(byte_length + relativeEnd, 0);
|
||||
} else {
|
||||
fin = MathMin(relativeEnd, byte_length);
|
||||
fin = MinSimple(relativeEnd, byte_length);
|
||||
}
|
||||
|
||||
if (fin < first) {
|
||||
|
@ -16,8 +16,8 @@ var GetIterator;
|
||||
var GetMethod;
|
||||
var GlobalArray = global.Array;
|
||||
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
||||
var MathMax;
|
||||
var MathMin;
|
||||
var MaxSimple;
|
||||
var MinSimple;
|
||||
var ObjectIsFrozen;
|
||||
var ObjectDefineProperty;
|
||||
|
||||
@ -25,8 +25,8 @@ utils.Import(function(from) {
|
||||
FLAG_harmony_tolength = from.FLAG_harmony_tolength;
|
||||
GetIterator = from.GetIterator;
|
||||
GetMethod = from.GetMethod;
|
||||
MathMax = from.MathMax;
|
||||
MathMin = from.MathMin;
|
||||
MaxSimple = from.MaxSimple;
|
||||
MinSimple = from.MinSimple;
|
||||
ObjectIsFrozen = from.ObjectIsFrozen;
|
||||
ObjectDefineProperty = from.ObjectDefineProperty;
|
||||
});
|
||||
@ -37,28 +37,28 @@ function InnerArrayCopyWithin(target, start, end, array, length) {
|
||||
target = TO_INTEGER(target);
|
||||
var to;
|
||||
if (target < 0) {
|
||||
to = MathMax(length + target, 0);
|
||||
to = MaxSimple(length + target, 0);
|
||||
} else {
|
||||
to = MathMin(target, length);
|
||||
to = MinSimple(target, length);
|
||||
}
|
||||
|
||||
start = TO_INTEGER(start);
|
||||
var from;
|
||||
if (start < 0) {
|
||||
from = MathMax(length + start, 0);
|
||||
from = MaxSimple(length + start, 0);
|
||||
} else {
|
||||
from = MathMin(start, length);
|
||||
from = MinSimple(start, length);
|
||||
}
|
||||
|
||||
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
|
||||
var final;
|
||||
if (end < 0) {
|
||||
final = MathMax(length + end, 0);
|
||||
final = MaxSimple(length + end, 0);
|
||||
} 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;
|
||||
if (from < to && to < (from + count)) {
|
||||
direction = -1;
|
||||
|
@ -12,11 +12,11 @@
|
||||
// Imports
|
||||
|
||||
var GlobalObject = global.Object;
|
||||
var MathMax;
|
||||
var MaxSimple;
|
||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||
|
||||
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)) {
|
||||
timeout = INFINITY;
|
||||
} else {
|
||||
timeout = MathMax(0, timeout);
|
||||
timeout = MaxSimple(0, timeout);
|
||||
}
|
||||
}
|
||||
return %AtomicsFutexWait(ia, index, value, timeout);
|
||||
@ -158,14 +158,14 @@ function AtomicsFutexWakeJS(ia, index, count) {
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
count = MathMax(0, TO_INTEGER(count));
|
||||
count = MaxSimple(0, TO_INTEGER(count));
|
||||
return %AtomicsFutexWake(ia, index, count);
|
||||
}
|
||||
|
||||
function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
|
||||
CheckSharedInteger32TypedArray(ia);
|
||||
index1 = TO_INTEGER(index1);
|
||||
count = MathMax(0, TO_INTEGER(count));
|
||||
count = MaxSimple(0, TO_INTEGER(count));
|
||||
value = TO_INT32(value);
|
||||
index2 = TO_INTEGER(index2);
|
||||
if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
|
||||
|
@ -48,8 +48,8 @@ var InnerArraySome;
|
||||
var InnerArraySort;
|
||||
var InnerArrayToLocaleString;
|
||||
var IsNaN;
|
||||
var MathMax;
|
||||
var MathMin;
|
||||
var MaxSimple;
|
||||
var MinSimple;
|
||||
var PackedArrayReverse;
|
||||
|
||||
utils.Import(function(from) {
|
||||
@ -72,8 +72,8 @@ utils.Import(function(from) {
|
||||
InnerArraySort = from.InnerArraySort;
|
||||
InnerArrayToLocaleString = from.InnerArrayToLocaleString;
|
||||
IsNaN = from.IsNaN;
|
||||
MathMax = from.MathMax;
|
||||
MathMin = from.MathMin;
|
||||
MaxSimple = from.MaxSimple;
|
||||
MinSimple = from.MinSimple;
|
||||
PackedArrayReverse = from.PackedArrayReverse;
|
||||
});
|
||||
|
||||
@ -319,9 +319,9 @@ function TypedArraySlice(start, end) {
|
||||
|
||||
var k;
|
||||
if (relativeStart < 0) {
|
||||
k = MathMax(len + relativeStart, 0);
|
||||
k = MaxSimple(len + relativeStart, 0);
|
||||
} else {
|
||||
k = MathMin(relativeStart, len);
|
||||
k = MinSimple(relativeStart, len);
|
||||
}
|
||||
|
||||
var relativeEnd;
|
||||
@ -333,12 +333,12 @@ function TypedArraySlice(start, end) {
|
||||
|
||||
var final;
|
||||
if (relativeEnd < 0) {
|
||||
final = MathMax(len + relativeEnd, 0);
|
||||
final = MaxSimple(len + relativeEnd, 0);
|
||||
} 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);
|
||||
// The code below is the 'then' branch; the 'else' branch species
|
||||
// a memcpy. Because V8 doesn't canonicalize NaN, the difference is
|
||||
|
@ -13,14 +13,14 @@
|
||||
|
||||
var GlobalJSON = global.JSON;
|
||||
var InternalArray = utils.InternalArray;
|
||||
var MathMax;
|
||||
var MathMin;
|
||||
var MaxSimple;
|
||||
var MinSimple;
|
||||
var ObjectHasOwnProperty;
|
||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||
|
||||
utils.Import(function(from) {
|
||||
MathMax = from.MathMax;
|
||||
MathMin = from.MathMin;
|
||||
MaxSimple = from.MaxSimple;
|
||||
MinSimple = from.MinSimple;
|
||||
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
|
||||
});
|
||||
|
||||
@ -215,7 +215,7 @@ function JSONStringify(value, replacer, space) {
|
||||
}
|
||||
var gap;
|
||||
if (IS_NUMBER(space)) {
|
||||
space = MathMax(0, MathMin(TO_INTEGER(space), 10));
|
||||
space = MaxSimple(0, MinSimple(TO_INTEGER(space), 10));
|
||||
gap = %_SubString(" ", 0, space);
|
||||
} else if (IS_STRING(space)) {
|
||||
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 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 MAX_SIMPLE(argA, argB) = (argA < argB ? argB : argA);
|
||||
macro MIN_SIMPLE(argA, argB) = (argA < argB ? argA : argB);
|
||||
|
||||
# Private names.
|
||||
macro IS_PRIVATE(sym) = (%SymbolIsPrivate(sym));
|
||||
|
@ -186,6 +186,8 @@ function PostNatives(utils) {
|
||||
"MapIteratorNext",
|
||||
"MathMax",
|
||||
"MathMin",
|
||||
"MaxSimple",
|
||||
"MinSimple",
|
||||
"ObjectIsFrozen",
|
||||
"ObjectDefineProperty",
|
||||
"ObserveArrayMethods",
|
||||
|
@ -216,6 +216,20 @@ function ToPositiveInteger(x, rangeErrorIndex) {
|
||||
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
|
||||
@ -229,9 +243,11 @@ function ToPositiveInteger(x, rangeErrorIndex) {
|
||||
// Exports
|
||||
|
||||
utils.Export(function(to) {
|
||||
to.ToPositiveInteger = ToPositiveInteger;
|
||||
to.MaxSimple = MaxSimple;
|
||||
to.MinSimple = MinSimple;
|
||||
to.SameValue = SameValue;
|
||||
to.SameValueZero = SameValueZero;
|
||||
to.ToPositiveInteger = ToPositiveInteger;
|
||||
});
|
||||
|
||||
%InstallToContext([
|
||||
|
@ -18,6 +18,8 @@ var GlobalDataView = global.DataView;
|
||||
var GlobalObject = global.Object;
|
||||
var InternalArray = utils.InternalArray;
|
||||
var iteratorSymbol = utils.ImportNow("iterator_symbol");
|
||||
var MaxSimple;
|
||||
var MinSimple;
|
||||
var ToPositiveInteger;
|
||||
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
|
||||
|
||||
@ -42,6 +44,8 @@ TYPED_ARRAYS(DECLARE_GLOBALS)
|
||||
|
||||
utils.Import(function(from) {
|
||||
ArrayValues = from.ArrayValues;
|
||||
MaxSimple = from.MaxSimple;
|
||||
MinSimple = from.MinSimple;
|
||||
ToPositiveInteger = from.ToPositiveInteger;
|
||||
});
|
||||
|
||||
@ -213,15 +217,15 @@ function NAMESubArray(begin, end) {
|
||||
}
|
||||
|
||||
if (beginInt < 0) {
|
||||
beginInt = MAX_SIMPLE(0, srcLength + beginInt);
|
||||
beginInt = MaxSimple(0, srcLength + beginInt);
|
||||
} else {
|
||||
beginInt = MIN_SIMPLE(beginInt, srcLength);
|
||||
beginInt = MinSimple(beginInt, srcLength);
|
||||
}
|
||||
|
||||
if (endInt < 0) {
|
||||
endInt = MAX_SIMPLE(0, srcLength + endInt);
|
||||
endInt = MaxSimple(0, srcLength + endInt);
|
||||
} else {
|
||||
endInt = MIN_SIMPLE(endInt, srcLength);
|
||||
endInt = MinSimple(endInt, srcLength);
|
||||
}
|
||||
|
||||
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