Commit 7d383be9 authored by bmeurer's avatar bmeurer Committed by Commit bot

[crankshaft] Support all oddballs for truncating TaggedToI changes.

For inputs to truncating binary operations like <<, | or >>>, support
all Oddballs not just undefined, true and false. This unifies treatment
of these truncations in Crankshaft and TurboFan, and is very easy
nowadays, since the memory layout of Oddball and HeapNumber is
compatible.

R=yangguo@chromium.org
BUG=v8:5400

Review-Url: https://codereview.chromium.org/2452193003
Cr-Commit-Position: refs/heads/master@{#40608}
parent 9bc155b9
...@@ -318,7 +318,7 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) { ...@@ -318,7 +318,7 @@ OsrGuardType OsrGuardTypeOf(Operator const* op) {
V(LostPrecisionOrNaN) \ V(LostPrecisionOrNaN) \
V(NoReason) \ V(NoReason) \
V(NotAHeapNumber) \ V(NotAHeapNumber) \
V(NotAHeapNumberUndefinedBoolean) \ V(NotANumberOrOddball) \
V(NotASmi) \ V(NotASmi) \
V(OutOfBounds) \ V(OutOfBounds) \
V(WrongInstanceType) \ V(WrongInstanceType) \
......
...@@ -1818,8 +1818,7 @@ EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( ...@@ -1818,8 +1818,7 @@ EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
graph()->NewNode(machine()->Word32Equal(), instance_type, graph()->NewNode(machine()->Word32Equal(), instance_type,
jsgraph()->Int32Constant(ODDBALL_TYPE)); jsgraph()->Int32Constant(ODDBALL_TYPE));
if_false = efalse = graph()->NewNode( if_false = efalse = graph()->NewNode(
common()->DeoptimizeUnless( common()->DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball),
DeoptimizeReason::kNotAHeapNumberUndefinedBoolean),
check_oddball, frame_state, efalse, if_false); check_oddball, frame_state, efalse, if_false);
STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset); STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
......
...@@ -4538,34 +4538,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4538,34 +4538,12 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
__ cmp(scratch1, Operand(ip)); __ cmp(scratch1, Operand(ip));
if (instr->truncating()) { if (instr->truncating()) {
// Performs a truncating conversion of a floating point number as used by Label truncate;
// the JS bitwise operations. __ b(eq, &truncate);
Label no_heap_number, check_bools, check_false; __ CompareInstanceType(scratch1, scratch1, ODDBALL_TYPE);
__ b(ne, &no_heap_number); DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball);
__ bind(&truncate);
__ TruncateHeapNumberToI(input_reg, scratch2); __ TruncateHeapNumberToI(input_reg, scratch2);
__ b(&done);
// Check for Oddballs. Undefined/False is converted to zero and True to one
// for truncating conversions.
__ bind(&no_heap_number);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(scratch2, Operand(ip));
__ b(ne, &check_bools);
__ mov(input_reg, Operand::Zero());
__ b(&done);
__ bind(&check_bools);
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(scratch2, Operand(ip));
__ b(ne, &check_false);
__ mov(input_reg, Operand(1));
__ b(&done);
__ bind(&check_false);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(scratch2, Operand(ip));
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefinedBoolean);
__ mov(input_reg, Operand::Zero());
} else { } else {
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber); DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber);
......
...@@ -5181,30 +5181,18 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, ...@@ -5181,30 +5181,18 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr,
Label done; Label done;
if (instr->truncating()) { if (instr->truncating()) {
UseScratchRegisterScope temps(masm());
Register output = ToRegister(instr->result()); Register output = ToRegister(instr->result());
Label check_bools; Register input_map = temps.AcquireX();
Register input_instance_type = input_map;
// If it's not a heap number, jump to undefined check. Label truncate;
__ JumpIfNotHeapNumber(input, &check_bools); __ CompareObjectType(input, input_map, input_instance_type,
HEAP_NUMBER_TYPE);
// A heap number: load value and convert to int32 using truncating function. __ B(eq, &truncate);
__ Cmp(input_instance_type, ODDBALL_TYPE);
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball);
__ Bind(&truncate);
__ TruncateHeapNumberToI(output, input); __ TruncateHeapNumberToI(output, input);
__ B(&done);
__ Bind(&check_bools);
Register true_root = output;
Register false_root = scratch1;
__ LoadTrueFalseRoots(true_root, false_root);
__ Cmp(input, true_root);
__ Cset(output, eq);
__ Ccmp(input, false_root, ZFlag, ne);
__ B(eq, &done);
// Output contains zero, undefined is converted to zero for truncating
// conversions.
DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, instr,
DeoptimizeReason::kNotAHeapNumberUndefinedBoolean);
} else { } else {
Register output = ToRegister32(instr->result()); Register output = ToRegister32(instr->result());
DoubleRegister dbl_scratch2 = ToDoubleRegister(temp2); DoubleRegister dbl_scratch2 = ToDoubleRegister(temp2);
......
...@@ -4308,34 +4308,18 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { ...@@ -4308,34 +4308,18 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
__ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag)); __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
if (instr->truncating()) { if (instr->truncating()) {
Label no_heap_number, check_bools, check_false; Label truncate;
Label::Distance truncate_distance =
// Heap number map check. DeoptEveryNTimes() ? Label::kFar : Label::kNear;
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map()); factory()->heap_number_map());
__ j(not_equal, &no_heap_number, Label::kNear); __ j(equal, &truncate, truncate_distance);
__ push(input_reg);
__ CmpObjectType(input_reg, ODDBALL_TYPE, input_reg);
__ pop(input_reg);
DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotANumberOrOddball);
__ bind(&truncate);
__ TruncateHeapNumberToI(input_reg, input_reg); __ TruncateHeapNumberToI(input_reg, input_reg);
__ jmp(done);
__ bind(&no_heap_number);
// Check for Oddballs. Undefined/False is converted to zero and True to one
// for truncating conversions.
__ cmp(input_reg, factory()->undefined_value());
__ j(not_equal, &check_bools, Label::kNear);
__ Move(input_reg, Immediate(0));
__ jmp(done);
__ bind(&check_bools);
__ cmp(input_reg, factory()->true_value());
__ j(not_equal, &check_false, Label::kNear);
__ Move(input_reg, Immediate(1));
__ jmp(done);
__ bind(&check_false);
__ cmp(input_reg, factory()->false_value());
DeoptimizeIf(not_equal, instr,
DeoptimizeReason::kNotAHeapNumberUndefinedBoolean);
__ Move(input_reg, Immediate(0));
} else { } else {
XMMRegister scratch = ToDoubleRegister(instr->temp()); XMMRegister scratch = ToDoubleRegister(instr->temp());
DCHECK(!scratch.is(xmm0)); DCHECK(!scratch.is(xmm0));
......
...@@ -4487,36 +4487,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4487,36 +4487,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// of the if. // of the if.
if (instr->truncating()) { if (instr->truncating()) {
// Performs a truncating conversion of a floating point number as used by Label truncate;
// the JS bitwise operations. __ Branch(USE_DELAY_SLOT, &truncate, eq, scratch1, Operand(at));
Label no_heap_number, check_bools, check_false;
// Check HeapNumber map.
__ Branch(USE_DELAY_SLOT, &no_heap_number, ne, scratch1, Operand(at));
__ mov(scratch2, input_reg); // In delay slot. __ mov(scratch2, input_reg); // In delay slot.
__ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1,
Operand(ODDBALL_TYPE));
__ bind(&truncate);
__ TruncateHeapNumberToI(input_reg, scratch2); __ TruncateHeapNumberToI(input_reg, scratch2);
__ Branch(&done);
// Check for Oddballs. Undefined/False is converted to zero and True to one
// for truncating conversions.
__ bind(&no_heap_number);
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&check_bools, ne, input_reg, Operand(at));
DCHECK(ToRegister(instr->result()).is(input_reg));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
__ bind(&check_bools);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&check_false, ne, scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ li(input_reg, Operand(1)); // In delay slot.
__ bind(&check_false);
__ LoadRoot(at, Heap::kFalseValueRootIndex);
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefinedBoolean,
scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
} else { } else {
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1,
Operand(at)); Operand(at));
......
...@@ -4695,36 +4695,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { ...@@ -4695,36 +4695,14 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
// of the if. // of the if.
if (instr->truncating()) { if (instr->truncating()) {
// Performs a truncating conversion of a floating point number as used by Label truncate;
// the JS bitwise operations. __ Branch(USE_DELAY_SLOT, &truncate, eq, scratch1, Operand(at));
Label no_heap_number, check_bools, check_false;
// Check HeapNumber map.
__ Branch(USE_DELAY_SLOT, &no_heap_number, ne, scratch1, Operand(at));
__ mov(scratch2, input_reg); // In delay slot. __ mov(scratch2, input_reg); // In delay slot.
__ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotANumberOrOddball, scratch1,
Operand(ODDBALL_TYPE));
__ bind(&truncate);
__ TruncateHeapNumberToI(input_reg, scratch2); __ TruncateHeapNumberToI(input_reg, scratch2);
__ Branch(&done);
// Check for Oddballs. Undefined/False is converted to zero and True to one
// for truncating conversions.
__ bind(&no_heap_number);
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&check_bools, ne, input_reg, Operand(at));
DCHECK(ToRegister(instr->result()).is(input_reg));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
__ bind(&check_bools);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&check_false, ne, scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ li(input_reg, Operand(1)); // In delay slot.
__ bind(&check_false);
__ LoadRoot(at, Heap::kFalseValueRootIndex);
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumberUndefinedBoolean,
scratch2, Operand(at));
__ Branch(USE_DELAY_SLOT, &done);
__ mov(input_reg, zero_reg); // In delay slot.
} else { } else {
DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1, DeoptimizeIf(ne, instr, DeoptimizeReason::kNotAHeapNumber, scratch1,
Operand(at)); Operand(at));
......
...@@ -4594,34 +4594,17 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { ...@@ -4594,34 +4594,17 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
Register input_reg = ToRegister(instr->value()); Register input_reg = ToRegister(instr->value());
if (instr->truncating()) { if (instr->truncating()) {
Label no_heap_number, check_bools, check_false; Register input_map_reg = kScratchRegister;
Label truncate;
// Heap number map check. Label::Distance truncate_distance =
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), DeoptEveryNTimes() ? Label::kFar : Label::kNear;
Heap::kHeapNumberMapRootIndex); __ movp(input_map_reg, FieldOperand(input_reg, HeapObject::kMapOffset));
__ j(not_equal, &no_heap_number, Label::kNear); __ JumpIfRoot(input_map_reg, Heap::kHeapNumberMapRootIndex, &truncate,
truncate_distance);
__ CmpInstanceType(input_map_reg, ODDBALL_TYPE);
DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotANumberOrOddball);
__ bind(&truncate);
__ TruncateHeapNumberToI(input_reg, input_reg); __ TruncateHeapNumberToI(input_reg, input_reg);
__ jmp(done);
__ bind(&no_heap_number);
// Check for Oddballs. Undefined/False is converted to zero and True to one
// for truncating conversions.
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
__ j(not_equal, &check_bools, Label::kNear);
__ Set(input_reg, 0);
__ jmp(done);
__ bind(&check_bools);
__ CompareRoot(input_reg, Heap::kTrueValueRootIndex);
__ j(not_equal, &check_false, Label::kNear);
__ Set(input_reg, 1);
__ jmp(done);
__ bind(&check_false);
__ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
DeoptimizeIf(not_equal, instr,
DeoptimizeReason::kNotAHeapNumberUndefinedBoolean);
__ Set(input_reg, 0);
} else { } else {
XMMRegister scratch = ToDoubleRegister(instr->temp()); XMMRegister scratch = ToDoubleRegister(instr->temp());
DCHECK(!scratch.is(double_scratch0())); DCHECK(!scratch.is(double_scratch0()));
......
...@@ -10,70 +10,70 @@ ...@@ -10,70 +10,70 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define DEOPTIMIZE_REASON_LIST(V) \ #define DEOPTIMIZE_REASON_LIST(V) \
V(AccessCheck, "Access check needed") \ V(AccessCheck, "Access check needed") \
V(NoReason, "no reason") \ V(NoReason, "no reason") \
V(ConstantGlobalVariableAssignment, "Constant global variable assignment") \ V(ConstantGlobalVariableAssignment, "Constant global variable assignment") \
V(ConversionOverflow, "conversion overflow") \ V(ConversionOverflow, "conversion overflow") \
V(DivisionByZero, "division by zero") \ V(DivisionByZero, "division by zero") \
V(ExpectedHeapNumber, "Expected heap number") \ V(ExpectedHeapNumber, "Expected heap number") \
V(ExpectedSmi, "Expected smi") \ V(ExpectedSmi, "Expected smi") \
V(ForcedDeoptToRuntime, "Forced deopt to runtime") \ V(ForcedDeoptToRuntime, "Forced deopt to runtime") \
V(Hole, "hole") \ V(Hole, "hole") \
V(InstanceMigrationFailed, "instance migration failed") \ V(InstanceMigrationFailed, "instance migration failed") \
V(InsufficientTypeFeedbackForCall, "Insufficient type feedback for call") \ V(InsufficientTypeFeedbackForCall, "Insufficient type feedback for call") \
V(InsufficientTypeFeedbackForCallWithArguments, \ V(InsufficientTypeFeedbackForCallWithArguments, \
"Insufficient type feedback for call with arguments") \ "Insufficient type feedback for call with arguments") \
V(FastPathFailed, "Falling off the fast path") \ V(FastPathFailed, "Falling off the fast path") \
V(InsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \ V(InsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, \
"Insufficient type feedback for combined type of binary operation") \ "Insufficient type feedback for combined type of binary operation") \
V(InsufficientTypeFeedbackForGenericNamedAccess, \ V(InsufficientTypeFeedbackForGenericNamedAccess, \
"Insufficient type feedback for generic named access") \ "Insufficient type feedback for generic named access") \
V(InsufficientTypeFeedbackForGenericKeyedAccess, \ V(InsufficientTypeFeedbackForGenericKeyedAccess, \
"Insufficient type feedback for generic keyed access") \ "Insufficient type feedback for generic keyed access") \
V(InsufficientTypeFeedbackForLHSOfBinaryOperation, \ V(InsufficientTypeFeedbackForLHSOfBinaryOperation, \
"Insufficient type feedback for LHS of binary operation") \ "Insufficient type feedback for LHS of binary operation") \
V(InsufficientTypeFeedbackForRHSOfBinaryOperation, \ V(InsufficientTypeFeedbackForRHSOfBinaryOperation, \
"Insufficient type feedback for RHS of binary operation") \ "Insufficient type feedback for RHS of binary operation") \
V(KeyIsNegative, "key is negative") \ V(KeyIsNegative, "key is negative") \
V(LostPrecision, "lost precision") \ V(LostPrecision, "lost precision") \
V(LostPrecisionOrNaN, "lost precision or NaN") \ V(LostPrecisionOrNaN, "lost precision or NaN") \
V(MementoFound, "memento found") \ V(MementoFound, "memento found") \
V(MinusZero, "minus zero") \ V(MinusZero, "minus zero") \
V(NaN, "NaN") \ V(NaN, "NaN") \
V(NegativeKeyEncountered, "Negative key encountered") \ V(NegativeKeyEncountered, "Negative key encountered") \
V(NegativeValue, "negative value") \ V(NegativeValue, "negative value") \
V(NoCache, "no cache") \ V(NoCache, "no cache") \
V(NotAHeapNumber, "not a heap number") \ V(NotAHeapNumber, "not a heap number") \
V(NotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \ V(NotAHeapNumberUndefined, "not a heap number/undefined") \
V(NotAHeapNumberUndefined, "not a heap number/undefined") \ V(NotAJavaScriptObject, "not a JavaScript object") \
V(NotAJavaScriptObject, "not a JavaScript object") \ V(NotANumberOrOddball, "not a Number or Oddball") \
V(NotASmi, "not a Smi") \ V(NotASmi, "not a Smi") \
V(OutOfBounds, "out of bounds") \ V(OutOfBounds, "out of bounds") \
V(OutsideOfRange, "Outside of range") \ V(OutsideOfRange, "Outside of range") \
V(Overflow, "overflow") \ V(Overflow, "overflow") \
V(Proxy, "proxy") \ V(Proxy, "proxy") \
V(ReceiverWasAGlobalObject, "receiver was a global object") \ V(ReceiverWasAGlobalObject, "receiver was a global object") \
V(Smi, "Smi") \ V(Smi, "Smi") \
V(TooManyArguments, "too many arguments") \ V(TooManyArguments, "too many arguments") \
V(TracingElementsTransitions, "Tracing elements transitions") \ V(TracingElementsTransitions, "Tracing elements transitions") \
V(TypeMismatchBetweenFeedbackAndConstant, \ V(TypeMismatchBetweenFeedbackAndConstant, \
"Type mismatch between feedback and constant") \ "Type mismatch between feedback and constant") \
V(UnexpectedCellContentsInConstantGlobalStore, \ V(UnexpectedCellContentsInConstantGlobalStore, \
"Unexpected cell contents in constant global store") \ "Unexpected cell contents in constant global store") \
V(UnexpectedCellContentsInGlobalStore, \ V(UnexpectedCellContentsInGlobalStore, \
"Unexpected cell contents in global store") \ "Unexpected cell contents in global store") \
V(UnexpectedObject, "unexpected object") \ V(UnexpectedObject, "unexpected object") \
V(UnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \ V(UnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation") \
V(UnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \ V(UnknownMapInPolymorphicAccess, "Unknown map in polymorphic access") \
V(UnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \ V(UnknownMapInPolymorphicCall, "Unknown map in polymorphic call") \
V(UnknownMapInPolymorphicElementAccess, \ V(UnknownMapInPolymorphicElementAccess, \
"Unknown map in polymorphic element access") \ "Unknown map in polymorphic element access") \
V(UnknownMap, "Unknown map") \ V(UnknownMap, "Unknown map") \
V(ValueMismatch, "value mismatch") \ V(ValueMismatch, "value mismatch") \
V(WrongInstanceType, "wrong instance type") \ V(WrongInstanceType, "wrong instance type") \
V(WrongMap, "wrong map") \ V(WrongMap, "wrong map") \
V(UndefinedOrNullInForIn, "null or undefined in for-in") \ V(UndefinedOrNullInForIn, "null or undefined in for-in") \
V(UndefinedOrNullInToObject, "null or undefined in ToObject") V(UndefinedOrNullInToObject, "null or undefined in ToObject")
enum class DeoptimizeReason : uint8_t { enum class DeoptimizeReason : uint8_t {
......
...@@ -270,8 +270,8 @@ BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object, ...@@ -270,8 +270,8 @@ BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object,
Kind kind) const { Kind kind) const {
Kind new_kind = GENERIC; Kind new_kind = GENERIC;
bool is_truncating = Token::IsTruncatingBinaryOp(op()); bool is_truncating = Token::IsTruncatingBinaryOp(op());
if (object->IsBoolean() && is_truncating) { if (object->IsOddball() && is_truncating) {
// Booleans will be automatically truncated by HChange. // Oddballs will be automatically truncated by HChange.
new_kind = INT32; new_kind = INT32;
} else if (object->IsUndefined(isolate_)) { } else if (object->IsUndefined(isolate_)) {
// Undefined will be automatically truncated by HChange. // Undefined will be automatically truncated by HChange.
......
// Copyright 2016 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: --allow-natives-syntax
(function() {
function foo(x, y) { return x << y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
(function() {
function foo(x, y) { return x >> y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
(function() {
function foo(x, y) { return x >>> y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
(function() {
function foo(x, y) { return x ^ y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
(function() {
function foo(x, y) { return x | y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
(function() {
function foo(x, y) { return x & y; }
foo(1.1, 0.1);
%BaselineFunctionOnNextCall(foo);
foo(0.1, 1.1);
%OptimizeFunctionOnNextCall(foo);
foo(undefined, 1.1);
assertOptimized(foo);
foo(1.1, undefined);
assertOptimized(foo);
foo(null, 1.1);
assertOptimized(foo);
foo(1.1, null);
assertOptimized(foo);
foo(true, 1.1);
assertOptimized(foo);
foo(1.1, true);
assertOptimized(foo);
foo(false, 1.1);
assertOptimized(foo);
foo(1.1, false);
assertOptimized(foo);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment