MIPS: Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps and comparisons

Port r12961 (96c0e493)

BUG=
TEST=

Review URL: https://codereview.chromium.org/11280080
Patch from Akos Palfi <palfia@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13014 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
jkummerow@chromium.org 2012-11-20 14:11:53 +00:00
parent 8c5bf4a7e0
commit 0620b1d0d7
8 changed files with 377 additions and 546 deletions

View File

@ -42,8 +42,7 @@ namespace internal {
static void EmitIdenticalObjectComparison(MacroAssembler* masm,
Label* slow,
Condition cc,
bool never_nan_nan);
Condition cc);
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
Register lhs,
Register rhs,
@ -627,24 +626,6 @@ void FloatingPointHelper::LoadSmis(MacroAssembler* masm,
}
void FloatingPointHelper::LoadOperands(
MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* slow) {
// Load right operand (a0) to f12 or a2/a3.
LoadNumber(masm, destination,
a0, f14, a2, a3, heap_number_map, scratch1, scratch2, slow);
// Load left operand (a1) to f14 or a0/a1.
LoadNumber(masm, destination,
a1, f12, a0, a1, heap_number_map, scratch1, scratch2, slow);
}
void FloatingPointHelper::LoadNumber(MacroAssembler* masm,
Destination destination,
Register object,
@ -922,14 +903,15 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
!scratch1.is(scratch3) &&
!scratch2.is(scratch3));
Label done;
Label done, maybe_undefined;
__ UntagAndJumpIfSmi(dst, object, &done);
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
"HeapNumberMap register clobbered.");
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_int32);
__ JumpIfNotHeapNumber(object, heap_number_map, scratch1, &maybe_undefined);
// Object is a heap number.
// Convert the floating point value to a 32-bit integer.
@ -983,6 +965,14 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm,
__ Subu(dst, zero_reg, dst);
__ bind(&skip_sub);
}
__ Branch(&done);
__ bind(&maybe_undefined);
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(not_int32, ne, object, Operand(at));
// |undefined| is truncated to 0.
__ li(dst, Operand(Smi::FromInt(0)));
// Fall through.
__ bind(&done);
}
@ -1183,17 +1173,13 @@ void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
// for "identity and not NaN".
static void EmitIdenticalObjectComparison(MacroAssembler* masm,
Label* slow,
Condition cc,
bool never_nan_nan) {
Condition cc) {
Label not_identical;
Label heap_number, return_equal;
Register exp_mask_reg = t5;
__ Branch(&not_identical, ne, a0, Operand(a1));
// The two objects are identical. If we know that one of them isn't NaN then
// we now know they test equal.
if (cc != eq || !never_nan_nan) {
__ li(exp_mask_reg, Operand(HeapNumber::kExponentMask));
// Test for NaN. Sadly, we can't just compare to factory->nan_value(),
@ -1227,7 +1213,6 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
}
}
}
}
__ bind(&return_equal);
@ -1240,7 +1225,6 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
}
__ Ret();
if (cc != eq || !never_nan_nan) {
// For less and greater we don't have to check for NaN since the result of
// x < x is false regardless. For the others here is some code to check
// for NaN.
@ -1279,7 +1263,6 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
__ Ret();
}
// No fall through here.
}
__ bind(&not_identical);
}
@ -1752,15 +1735,40 @@ void NumberToStringStub::Generate(MacroAssembler* masm) {
}
// On entry lhs_ (lhs) and rhs_ (rhs) are the things to be compared.
// On exit, v0 is 0, positive, or negative (smi) to indicate the result
// of the comparison.
void CompareStub::Generate(MacroAssembler* masm) {
static void ICCompareStub_CheckInputType(MacroAssembler* masm,
Register input,
Register scratch,
CompareIC::State expected,
Label* fail) {
Label ok;
if (expected == CompareIC::SMI) {
__ JumpIfNotSmi(input, fail);
} else if (expected == CompareIC::HEAP_NUMBER) {
__ JumpIfSmi(input, &ok);
__ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
DONT_DO_SMI_CHECK);
}
// We could be strict about symbol/string here, but as long as
// hydrogen doesn't care, the stub doesn't have to care either.
__ bind(&ok);
}
// On entry a1 and a2 are the values to be compared.
// On exit a0 is 0, positive or negative to indicate the result of
// the comparison.
void ICCompareStub::GenerateGeneric(MacroAssembler* masm) {
Register lhs = a1;
Register rhs = a0;
Condition cc = GetCondition();
Label miss;
ICCompareStub_CheckInputType(masm, lhs, a2, left_, &miss);
ICCompareStub_CheckInputType(masm, rhs, a3, right_, &miss);
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles;
if (include_smi_compare_) {
Label not_two_smis, smi_done;
__ Or(a2, a1, a0);
__ JumpIfNotSmi(a2, &not_two_smis);
@ -1769,26 +1777,19 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ Ret(USE_DELAY_SLOT);
__ subu(v0, a1, a0);
__ bind(&not_two_smis);
} else if (FLAG_debug_code) {
__ Or(a2, a1, a0);
__ And(a2, a2, kSmiTagMask);
__ Assert(ne, "CompareStub: unexpected smi operands.",
a2, Operand(zero_reg));
}
// NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi.
// Handle the case where the objects are identical. Either returns the answer
// or goes to slow. Only falls through if the objects were not identical.
EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
EmitIdenticalObjectComparison(masm, &slow, cc);
// If either is a Smi (we know that not both are), then they can only
// be strictly equal if the other is a HeapNumber.
STATIC_ASSERT(kSmiTag == 0);
ASSERT_EQ(0, Smi::FromInt(0));
__ And(t2, lhs_, Operand(rhs_));
__ And(t2, lhs, Operand(rhs));
__ JumpIfNotSmi(t2, &not_smis, t0);
// One operand is a smi. EmitSmiNonsmiComparison generates code that can:
// 1) Return the answer.
@ -1798,8 +1799,8 @@ void CompareStub::Generate(MacroAssembler* masm) {
// In cases 3 and 4 we have found out we were dealing with a number-number
// comparison and the numbers have been loaded into f12 and f14 as doubles,
// or in GP registers (a0, a1, a2, a3) depending on the presence of the FPU.
EmitSmiNonsmiComparison(masm, lhs_, rhs_,
&both_loaded_as_doubles, &slow, strict_);
EmitSmiNonsmiComparison(masm, lhs, rhs,
&both_loaded_as_doubles, &slow, strict());
__ bind(&both_loaded_as_doubles);
// f12, f14 are the double representations of the left hand side
@ -1835,7 +1836,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ bind(&nan);
// NaN comparisons always fail.
// Load whatever we need in v0 to make the comparison fail.
if (cc_ == lt || cc_ == le) {
if (cc == lt || cc == le) {
__ li(v0, Operand(GREATER));
} else {
__ li(v0, Operand(LESS));
@ -1844,20 +1845,20 @@ void CompareStub::Generate(MacroAssembler* masm) {
} else {
// Checks for NaN in the doubles we have loaded. Can return the answer or
// fall through if neither is a NaN. Also binds rhs_not_nan.
EmitNanCheck(masm, cc_);
EmitNanCheck(masm, cc);
// Compares two doubles that are not NaNs. Returns the answer.
// Never falls through.
EmitTwoNonNanDoubleComparison(masm, cc_);
EmitTwoNonNanDoubleComparison(masm, cc);
}
__ bind(&not_smis);
// At this point we know we are dealing with two different objects,
// and neither of them is a Smi. The objects are in lhs_ and rhs_.
if (strict_) {
if (strict()) {
// This returns non-equal for some object types, or falls through if it
// was not lucky.
EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
}
Label check_for_symbols;
@ -1867,38 +1868,38 @@ void CompareStub::Generate(MacroAssembler* masm) {
// that case. If the inputs are not doubles then jumps to check_for_symbols.
// In this case a2 will contain the type of lhs_.
EmitCheckForTwoHeapNumbers(masm,
lhs_,
rhs_,
lhs,
rhs,
&both_loaded_as_doubles,
&check_for_symbols,
&flat_string_check);
__ bind(&check_for_symbols);
if (cc_ == eq && !strict_) {
if (cc == eq && !strict()) {
// Returns an answer for two symbols or two detectable objects.
// Otherwise jumps to string case or not both strings case.
// Assumes that a2 is the type of lhs_ on entry.
EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
EmitCheckForSymbolsOrObjects(masm, lhs, rhs, &flat_string_check, &slow);
}
// Check for both being sequential ASCII strings, and inline if that is the
// case.
__ bind(&flat_string_check);
__ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, a2, a3, &slow);
__ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs, rhs, a2, a3, &slow);
__ IncrementCounter(isolate->counters()->string_compare_native(), 1, a2, a3);
if (cc_ == eq) {
if (cc == eq) {
StringCompareStub::GenerateFlatAsciiStringEquals(masm,
lhs_,
rhs_,
lhs,
rhs,
a2,
a3,
t0);
} else {
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
lhs_,
rhs_,
lhs,
rhs,
a2,
a3,
t0,
@ -1909,18 +1910,18 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ bind(&slow);
// Prepare for call to builtin. Push object pointers, a0 (lhs) first,
// a1 (rhs) second.
__ Push(lhs_, rhs_);
__ Push(lhs, rhs);
// Figure out which native to call and setup the arguments.
Builtins::JavaScript native;
if (cc_ == eq) {
native = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
if (cc == eq) {
native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
} else {
native = Builtins::COMPARE;
int ncr; // NaN compare result.
if (cc_ == lt || cc_ == le) {
if (cc == lt || cc == le) {
ncr = GREATER;
} else {
ASSERT(cc_ == gt || cc_ == ge); // Remaining cases.
ASSERT(cc == gt || cc == ge); // Remaining cases.
ncr = LESS;
}
__ li(a0, Operand(Smi::FromInt(ncr)));
@ -1930,6 +1931,9 @@ void CompareStub::Generate(MacroAssembler* masm) {
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
__ InvokeBuiltin(native, JUMP_FUNCTION);
__ bind(&miss);
GenerateMiss(masm);
}
@ -2370,20 +2374,23 @@ void UnaryOpStub::GenerateGenericCodeFallback(
}
void BinaryOpStub::Initialize() {
platform_specific_bit_ = CpuFeatures::IsSupported(FPU);
}
void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
Label get_result;
__ Push(a1, a0);
__ li(a2, Operand(Smi::FromInt(MinorKey())));
__ li(a1, Operand(Smi::FromInt(op_)));
__ li(a0, Operand(Smi::FromInt(operands_type_)));
__ Push(a2, a1, a0);
__ push(a2);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
masm->isolate()),
5,
3,
1);
}
@ -2394,59 +2401,8 @@ void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
}
void BinaryOpStub::Generate(MacroAssembler* masm) {
// Explicitly allow generation of nested stubs. It is safe here because
// generation code does not use any raw pointers.
AllowStubCallsScope allow_stub_calls(masm, true);
switch (operands_type_) {
case BinaryOpIC::UNINITIALIZED:
GenerateTypeTransition(masm);
break;
case BinaryOpIC::SMI:
GenerateSmiStub(masm);
break;
case BinaryOpIC::INT32:
GenerateInt32Stub(masm);
break;
case BinaryOpIC::HEAP_NUMBER:
GenerateHeapNumberStub(masm);
break;
case BinaryOpIC::ODDBALL:
GenerateOddballStub(masm);
break;
case BinaryOpIC::BOTH_STRING:
GenerateBothStringStub(masm);
break;
case BinaryOpIC::STRING:
GenerateStringStub(masm);
break;
case BinaryOpIC::GENERIC:
GenerateGeneric(masm);
break;
default:
UNREACHABLE();
}
}
void BinaryOpStub::PrintName(StringStream* stream) {
const char* op_name = Token::Name(op_);
const char* overwrite_name;
switch (mode_) {
case NO_OVERWRITE: overwrite_name = "Alloc"; break;
case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
default: overwrite_name = "UnknownOverwrite"; break;
}
stream->Add("BinaryOpStub_%s_%s_%s",
op_name,
overwrite_name,
BinaryOpIC::GetName(operands_type_));
}
void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
Token::Value op) {
Register left = a1;
Register right = a0;
@ -2457,7 +2413,7 @@ void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
STATIC_ASSERT(kSmiTag == 0);
Label not_smi_result;
switch (op_) {
switch (op) {
case Token::ADD:
__ AdduAndCheckForOverflow(v0, left, right, scratch1);
__ RetOnNoOverflow(scratch1);
@ -2600,10 +2556,24 @@ void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
}
void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* gc_required,
OverwriteMode mode);
void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
BinaryOpIC::TypeInfo left_type,
BinaryOpIC::TypeInfo right_type,
bool smi_operands,
Label* not_numbers,
Label* gc_required) {
Label* gc_required,
Label* miss,
Token::Value op,
OverwriteMode mode) {
Register left = a1;
Register right = a0;
Register scratch1 = t3;
@ -2615,11 +2585,17 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
__ AssertSmi(left);
__ AssertSmi(right);
}
if (left_type == BinaryOpIC::SMI) {
__ JumpIfNotSmi(left, miss);
}
if (right_type == BinaryOpIC::SMI) {
__ JumpIfNotSmi(right, miss);
}
Register heap_number_map = t2;
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
switch (op_) {
switch (op) {
case Token::ADD:
case Token::SUB:
case Token::MUL:
@ -2629,25 +2605,44 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
// depending on whether FPU is available or not.
FloatingPointHelper::Destination destination =
CpuFeatures::IsSupported(FPU) &&
op_ != Token::MOD ?
op != Token::MOD ?
FloatingPointHelper::kFPURegisters :
FloatingPointHelper::kCoreRegisters;
// Allocate new heap number for result.
Register result = s0;
GenerateHeapResultAllocation(
masm, result, heap_number_map, scratch1, scratch2, gc_required);
BinaryOpStub_GenerateHeapResultAllocation(
masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
// Load the operands.
if (smi_operands) {
FloatingPointHelper::LoadSmis(masm, destination, scratch1, scratch2);
} else {
FloatingPointHelper::LoadOperands(masm,
destination,
heap_number_map,
scratch1,
scratch2,
not_numbers);
// Load right operand to f14 or a2/a3.
if (right_type == BinaryOpIC::INT32) {
FloatingPointHelper::LoadNumberAsInt32Double(
masm, right, destination, f14, f16, a2, a3, heap_number_map,
scratch1, scratch2, f2, miss);
} else {
Label* fail = (right_type == BinaryOpIC::HEAP_NUMBER) ? miss
: not_numbers;
FloatingPointHelper::LoadNumber(
masm, destination, right, f14, a2, a3, heap_number_map,
scratch1, scratch2, fail);
}
// Load left operand to f12 or a0/a1. This keeps a0/a1 intact if it
// jumps to |miss|.
if (left_type == BinaryOpIC::INT32) {
FloatingPointHelper::LoadNumberAsInt32Double(
masm, left, destination, f12, f16, a0, a1, heap_number_map,
scratch1, scratch2, f2, miss);
} else {
Label* fail = (left_type == BinaryOpIC::HEAP_NUMBER) ? miss
: not_numbers;
FloatingPointHelper::LoadNumber(
masm, destination, left, f12, a0, a1, heap_number_map,
scratch1, scratch2, fail);
}
}
// Calculate the result.
@ -2656,7 +2651,7 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
// f12: Left value.
// f14: Right value.
CpuFeatures::Scope scope(FPU);
switch (op_) {
switch (op) {
case Token::ADD:
__ add_d(f10, f12, f14);
break;
@ -2682,7 +2677,7 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
} else {
// Call the C function to handle the double operation.
FloatingPointHelper::CallCCodeForDoubleOperation(masm,
op_,
op,
result,
scratch1);
if (FLAG_debug_code) {
@ -2722,7 +2717,7 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
not_numbers);
}
Label result_not_a_smi;
switch (op_) {
switch (op) {
case Token::BIT_OR:
__ Or(a2, a3, Operand(a2));
break;
@ -2772,8 +2767,9 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
__ AllocateHeapNumber(
result, scratch1, scratch2, heap_number_map, gc_required);
} else {
GenerateHeapResultAllocation(
masm, result, heap_number_map, scratch1, scratch2, gc_required);
BinaryOpStub_GenerateHeapResultAllocation(
masm, result, heap_number_map, scratch1, scratch2, gc_required,
mode);
}
// a2: Answer as signed int32.
@ -2788,7 +2784,7 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
// mentioned above SHR needs to always produce a positive result.
CpuFeatures::Scope scope(FPU);
__ mtc1(a2, f0);
if (op_ == Token::SHR) {
if (op == Token::SHR) {
__ Cvt_d_uw(f0, f0, f22);
} else {
__ cvt_d_w(f0, f0);
@ -2815,12 +2811,14 @@ void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
// Generate the smi code. If the operation on smis are successful this return is
// generated. If the result is not a smi and heap number allocation is not
// requested the code falls through. If number allocation is requested but a
// heap number cannot be allocated the code jumps to the lable gc_required.
void BinaryOpStub::GenerateSmiCode(
// heap number cannot be allocated the code jumps to the label gc_required.
void BinaryOpStub_GenerateSmiCode(
MacroAssembler* masm,
Label* use_runtime,
Label* gc_required,
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
Token::Value op,
BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
OverwriteMode mode) {
Label not_smis;
Register left = a1;
@ -2833,12 +2831,14 @@ void BinaryOpStub::GenerateSmiCode(
__ JumpIfNotSmi(scratch1, &not_smis);
// If the smi-smi operation results in a smi return is generated.
GenerateSmiSmiOperation(masm);
BinaryOpStub_GenerateSmiSmiOperation(masm, op);
// If heap number results are possible generate the result in an allocated
// heap number.
if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
GenerateFPOperation(masm, true, use_runtime, gc_required);
if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
BinaryOpStub_GenerateFPOperation(
masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
use_runtime, gc_required, &not_smis, op, mode);
}
__ bind(&not_smis);
}
@ -2850,14 +2850,14 @@ void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
if (result_type_ == BinaryOpIC::UNINITIALIZED ||
result_type_ == BinaryOpIC::SMI) {
// Only allow smi results.
GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
BinaryOpStub_GenerateSmiCode(
masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_);
} else {
// Allow heap number result and don't make a transition if a heap number
// cannot be allocated.
GenerateSmiCode(masm,
&call_runtime,
&call_runtime,
ALLOW_HEAPNUMBER_RESULTS);
BinaryOpStub_GenerateSmiCode(
masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS,
mode_);
}
// Code falls through if the result is not returned as either a smi or heap
@ -2865,22 +2865,14 @@ void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
GenerateTypeTransition(masm);
__ bind(&call_runtime);
GenerateRegisterArgsPush(masm);
GenerateCallRuntime(masm);
}
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
ASSERT(operands_type_ == BinaryOpIC::STRING);
// Try to add arguments as strings, otherwise, transition to the generic
// BinaryOpIC type.
GenerateAddStrings(masm);
GenerateTypeTransition(masm);
}
void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
Label call_runtime;
ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
ASSERT(left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING);
ASSERT(op_ == Token::ADD);
// If both arguments are strings, call the string add stub.
// Otherwise, do a transition.
@ -2909,7 +2901,7 @@ void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
ASSERT(operands_type_ == BinaryOpIC::INT32);
ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32);
Register left = a1;
Register right = a0;
@ -2932,7 +2924,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
Label skip;
__ Or(scratch1, left, right);
__ JumpIfNotSmi(scratch1, &skip);
GenerateSmiSmiOperation(masm);
BinaryOpStub_GenerateSmiSmiOperation(masm, op_);
// Fall through if the result is not a smi.
__ bind(&skip);
@ -2942,6 +2934,15 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
case Token::MUL:
case Token::DIV:
case Token::MOD: {
// It could be that only SMIs have been seen at either the left
// or the right operand. For precise type feedback, patch the IC
// again if this changes.
if (left_type_ == BinaryOpIC::SMI) {
__ JumpIfNotSmi(left, &transition);
}
if (right_type_ == BinaryOpIC::SMI) {
__ JumpIfNotSmi(right, &transition);
}
// Load both operands and check that they are 32-bit integer.
// Jump to type transition if they are not. The registers a0 and a1 (right
// and left) are preserved for the runtime call.
@ -3038,12 +3039,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
: BinaryOpIC::INT32)) {
// We are using FPU registers so s0 is available.
heap_number_result = s0;
GenerateHeapResultAllocation(masm,
BinaryOpStub_GenerateHeapResultAllocation(masm,
heap_number_result,
heap_number_map,
scratch1,
scratch2,
&call_runtime);
&call_runtime,
mode_);
__ mov(v0, heap_number_result);
__ sdc1(f10, FieldMemOperand(v0, HeapNumber::kValueOffset));
__ Ret();
@ -3061,12 +3063,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
// Allocate a heap number to store the result.
heap_number_result = s0;
GenerateHeapResultAllocation(masm,
BinaryOpStub_GenerateHeapResultAllocation(masm,
heap_number_result,
heap_number_map,
scratch1,
scratch2,
&pop_and_call_runtime);
&pop_and_call_runtime,
mode_);
// Load the left value from the value saved on the stack.
__ Pop(a1, a0);
@ -3175,12 +3178,13 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
__ bind(&return_heap_number);
heap_number_result = t1;
GenerateHeapResultAllocation(masm,
BinaryOpStub_GenerateHeapResultAllocation(masm,
heap_number_result,
heap_number_map,
scratch1,
scratch2,
&call_runtime);
&call_runtime,
mode_);
if (CpuFeatures::IsSupported(FPU)) {
CpuFeatures::Scope scope(FPU);
@ -3224,6 +3228,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
}
__ bind(&call_runtime);
GenerateRegisterArgsPush(masm);
GenerateCallRuntime(masm);
}
@ -3262,20 +3267,32 @@ void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
Label call_runtime;
GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
Label call_runtime, transition;
BinaryOpStub_GenerateFPOperation(
masm, left_type_, right_type_, false,
&transition, &call_runtime, &transition, op_, mode_);
__ bind(&transition);
GenerateTypeTransition(masm);
__ bind(&call_runtime);
GenerateRegisterArgsPush(masm);
GenerateCallRuntime(masm);
}
void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
Label call_runtime, call_string_add_or_runtime;
Label call_runtime, call_string_add_or_runtime, transition;
GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
BinaryOpStub_GenerateSmiCode(
masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_);
GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime);
BinaryOpStub_GenerateFPOperation(
masm, left_type_, right_type_, false,
&call_string_add_or_runtime, &call_runtime, &transition, op_, mode_);
__ bind(&transition);
GenerateTypeTransition(masm);
__ bind(&call_string_add_or_runtime);
if (op_ == Token::ADD) {
@ -3283,6 +3300,7 @@ void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
}
__ bind(&call_runtime);
GenerateRegisterArgsPush(masm);
GenerateCallRuntime(masm);
}
@ -3318,63 +3336,20 @@ void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
}
void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
GenerateRegisterArgsPush(masm);
switch (op_) {
case Token::ADD:
__ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
break;
case Token::SUB:
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
break;
case Token::MUL:
__ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
break;
case Token::DIV:
__ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
break;
case Token::MOD:
__ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
break;
case Token::BIT_OR:
__ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
break;
case Token::BIT_AND:
__ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
break;
case Token::BIT_XOR:
__ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
break;
case Token::SAR:
__ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
break;
case Token::SHR:
__ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
break;
case Token::SHL:
__ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
break;
default:
UNREACHABLE();
}
}
void BinaryOpStub::GenerateHeapResultAllocation(
MacroAssembler* masm,
void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* gc_required) {
Label* gc_required,
OverwriteMode mode) {
// Code below will scratch result if allocation fails. To keep both arguments
// intact for the runtime call result cannot be one of these.
ASSERT(!result.is(a0) && !result.is(a1));
if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) {
if (mode == OVERWRITE_LEFT || mode == OVERWRITE_RIGHT) {
Label skip_allocation, allocated;
Register overwritable_operand = mode_ == OVERWRITE_LEFT ? a1 : a0;
Register overwritable_operand = mode == OVERWRITE_LEFT ? a1 : a0;
// If the overwritable operand is already an object, we skip the
// allocation of a heap number.
__ JumpIfNotSmi(overwritable_operand, &skip_allocation);
@ -3387,7 +3362,7 @@ void BinaryOpStub::GenerateHeapResultAllocation(
__ mov(result, overwritable_operand);
__ bind(&allocated);
} else {
ASSERT(mode_ == NO_OVERWRITE);
ASSERT(mode == NO_OVERWRITE);
__ AllocateHeapNumber(
result, scratch1, scratch2, heap_number_map, gc_required);
}
@ -5599,45 +5574,6 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
}
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
void CompareStub::PrintName(StringStream* stream) {
ASSERT((lhs_.is(a0) && rhs_.is(a1)) ||
(lhs_.is(a1) && rhs_.is(a0)));
const char* cc_name;
switch (cc_) {
case lt: cc_name = "LT"; break;
case gt: cc_name = "GT"; break;
case le: cc_name = "LE"; break;
case ge: cc_name = "GE"; break;
case eq: cc_name = "EQ"; break;
case ne: cc_name = "NE"; break;
default: cc_name = "UnknownCondition"; break;
}
bool is_equality = cc_ == eq || cc_ == ne;
stream->Add("CompareStub_%s", cc_name);
stream->Add(lhs_.is(a0) ? "_a0" : "_a1");
stream->Add(rhs_.is(a0) ? "_a0" : "_a1");
if (strict_ && is_equality) stream->Add("_STRICT");
if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
if (!include_number_compare_) stream->Add("_NO_NUMBER");
if (!include_smi_compare_) stream->Add("_NO_SMI");
}
int CompareStub::MinorKey() {
// Encode the two parameters in a unique 16 bit value.
ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
ASSERT((lhs_.is(a0) && rhs_.is(a1)) ||
(lhs_.is(a1) && rhs_.is(a0)));
return ConditionField::encode(static_cast<unsigned>(cc_))
| RegisterField::encode(lhs_.is(a0))
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
| IncludeSmiCompareField::encode(include_smi_compare_);
}
// StringCharCodeAtGenerator.
void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
Label flat_string;
@ -6829,7 +6765,7 @@ void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::SMIS);
ASSERT(state_ == CompareIC::SMI);
Label miss;
__ Or(a2, a1, a0);
__ JumpIfNotSmi(a2, &miss);
@ -6851,18 +6787,18 @@ void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::HEAP_NUMBERS);
ASSERT(state_ == CompareIC::HEAP_NUMBER);
Label generic_stub;
Label unordered, maybe_undefined1, maybe_undefined2;
Label miss;
__ And(a2, a1, Operand(a0));
__ JumpIfSmi(a2, &generic_stub);
__ GetObjectType(a0, a2, a2);
__ Branch(&maybe_undefined1, ne, a2, Operand(HEAP_NUMBER_TYPE));
__ GetObjectType(a1, a2, a2);
__ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE));
if (left_ == CompareIC::SMI) {
__ JumpIfNotSmi(a1, &miss);
}
if (right_ == CompareIC::SMI) {
__ JumpIfNotSmi(a0, &miss);
}
// Inlining the double comparison and falling back to the general compare
// stub if NaN is involved or FPU is unsupported.
@ -6870,10 +6806,33 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
CpuFeatures::Scope scope(FPU);
// Load left and right operand.
__ Subu(a2, a1, Operand(kHeapObjectTag));
__ ldc1(f0, MemOperand(a2, HeapNumber::kValueOffset));
Label done, left, left_smi, right_smi;
__ JumpIfSmi(a0, &right_smi);
__ CheckMap(a0, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined1,
DONT_DO_SMI_CHECK);
__ Subu(a2, a0, Operand(kHeapObjectTag));
__ ldc1(f2, MemOperand(a2, HeapNumber::kValueOffset));
__ Branch(&left);
__ bind(&right_smi);
__ SmiUntag(a2, a0); // Can't clobber a0 yet.
FPURegister single_scratch = f6;
__ mtc1(a2, single_scratch);
__ cvt_d_w(f2, single_scratch);
__ bind(&left);
__ JumpIfSmi(a1, &left_smi);
__ CheckMap(a1, a2, Heap::kHeapNumberMapRootIndex, &maybe_undefined2,
DONT_DO_SMI_CHECK);
__ Subu(a2, a1, Operand(kHeapObjectTag));
__ ldc1(f0, MemOperand(a2, HeapNumber::kValueOffset));
__ Branch(&done);
__ bind(&left_smi);
__ SmiUntag(a2, a1); // Can't clobber a1 yet.
single_scratch = f8;
__ mtc1(a2, single_scratch);
__ cvt_d_w(f0, single_scratch);
__ bind(&done);
// Return a result of -1, 0, or 1, or use CompareStub for NaNs.
Label fpu_eq, fpu_lt;
@ -6897,15 +6856,16 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
}
__ bind(&unordered);
CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, a1, a0);
__ bind(&generic_stub);
ICCompareStub stub(op_, CompareIC::GENERIC, CompareIC::GENERIC,
CompareIC::GENERIC);
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
__ bind(&maybe_undefined1);
if (Token::IsOrderedRelationalCompareOp(op_)) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&miss, ne, a0, Operand(at));
__ JumpIfSmi(a1, &unordered);
__ GetObjectType(a1, a2, a2);
__ Branch(&maybe_undefined2, ne, a2, Operand(HEAP_NUMBER_TYPE));
__ jmp(&unordered);
@ -6923,7 +6883,7 @@ void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::SYMBOLS);
ASSERT(state_ == CompareIC::SYMBOL);
Label miss;
// Registers containing left and right operands respectively.
@ -6961,7 +6921,7 @@ void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::STRINGS);
ASSERT(state_ == CompareIC::STRING);
Label miss;
bool equality = Token::IsEqualityOp(op_);
@ -7046,7 +7006,7 @@ void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
ASSERT(state_ == CompareIC::OBJECTS);
ASSERT(state_ == CompareIC::OBJECT);
Label miss;
__ And(a2, a1, Operand(a0));
__ JumpIfSmi(a2, &miss);

View File

@ -143,108 +143,6 @@ class UnaryOpStub: public CodeStub {
};
class BinaryOpStub: public CodeStub {
public:
BinaryOpStub(Token::Value op, OverwriteMode mode)
: op_(op),
mode_(mode),
operands_type_(BinaryOpIC::UNINITIALIZED),
result_type_(BinaryOpIC::UNINITIALIZED) {
use_fpu_ = CpuFeatures::IsSupported(FPU);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
BinaryOpStub(
int key,
BinaryOpIC::TypeInfo operands_type,
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
: op_(OpBits::decode(key)),
mode_(ModeBits::decode(key)),
use_fpu_(FPUBits::decode(key)),
operands_type_(operands_type),
result_type_(result_type) { }
private:
enum SmiCodeGenerateHeapNumberResults {
ALLOW_HEAPNUMBER_RESULTS,
NO_HEAPNUMBER_RESULTS
};
Token::Value op_;
OverwriteMode mode_;
bool use_fpu_;
// Operand type information determined at runtime.
BinaryOpIC::TypeInfo operands_type_;
BinaryOpIC::TypeInfo result_type_;
virtual void PrintName(StringStream* stream);
// Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
class OpBits: public BitField<Token::Value, 2, 7> {};
class FPUBits: public BitField<bool, 9, 1> {};
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
Major MajorKey() { return BinaryOp; }
int MinorKey() {
return OpBits::encode(op_)
| ModeBits::encode(mode_)
| FPUBits::encode(use_fpu_)
| OperandTypeInfoBits::encode(operands_type_)
| ResultTypeInfoBits::encode(result_type_);
}
void Generate(MacroAssembler* masm);
void GenerateGeneric(MacroAssembler* masm);
void GenerateSmiSmiOperation(MacroAssembler* masm);
void GenerateFPOperation(MacroAssembler* masm,
bool smi_operands,
Label* not_numbers,
Label* gc_required);
void GenerateSmiCode(MacroAssembler* masm,
Label* use_runtime,
Label* gc_required,
SmiCodeGenerateHeapNumberResults heapnumber_results);
void GenerateLoadArguments(MacroAssembler* masm);
void GenerateReturn(MacroAssembler* masm);
void GenerateUninitializedStub(MacroAssembler* masm);
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateBothStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);
void GenerateAddStrings(MacroAssembler* masm);
void GenerateCallRuntime(MacroAssembler* masm);
void GenerateHeapResultAllocation(MacroAssembler* masm,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* gc_required);
void GenerateRegisterArgsPush(MacroAssembler* masm);
void GenerateTypeTransition(MacroAssembler* masm);
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
virtual InlineCacheState GetICState() {
return BinaryOpIC::ToState(operands_type_);
}
virtual void FinishCode(Handle<Code> code) {
code->set_binary_op_type(operands_type_);
code->set_binary_op_result_type(result_type_);
}
friend class CodeGenerator;
};
class StringHelper : public AllStatic {
public:
// Generate code for copying characters using a simple loop. This should only
@ -724,20 +622,6 @@ class FloatingPointHelper : public AllStatic {
Register scratch1,
Register scratch2);
// Loads objects from a0 and a1 (right and left in binary operations) into
// floating point registers. Depending on the destination the values ends up
// either f14 and f12 or in a2/a3 and a0/a1 respectively. If the destination
// is floating point registers FPU must be supported. If core registers are
// requested when FPU is supported f12 and f14 will still be scratched. If
// either a0 or a1 is not a number (not smi and not heap number object) the
// not_number label is jumped to with a0 and a1 intact.
static void LoadOperands(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* not_number);
// Convert the smi or heap number in object to an int32 using the rules
// for ToInt32 as described in ECMAScript 9.5.: the value is truncated
// and brought into the range -2^31 .. +2^31 - 1.
@ -834,7 +718,12 @@ class FloatingPointHelper : public AllStatic {
Register heap_number_result,
Register scratch);
private:
// Loads the objects from |object| into floating point registers.
// Depending on |destination| the value ends up either in |dst| or
// in |dst1|/|dst2|. If |destination| is kFPURegisters, then FPU
// must be supported. If kCoreRegisters are requested and FPU is
// supported, |dst| will be scratched. If |object| is neither smi nor
// heap number, |not_number| is jumped to with |object| still intact.
static void LoadNumber(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register object,

View File

@ -4103,9 +4103,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
JumpPatchSite patch_site(masm_);
int count_value = expr->op() == Token::INC ? 1 : -1;
__ li(a1, Operand(Smi::FromInt(count_value)));
if (ShouldInlineSmiCase(expr->op())) {
__ li(a1, Operand(Smi::FromInt(count_value)));
__ AdduAndCheckForOverflow(v0, a0, a1, t0);
__ BranchOnOverflow(&stub_call, t0); // Do stub on overflow.
@ -4114,6 +4113,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
patch_site.EmitJumpIfSmi(v0, &done);
__ bind(&stub_call);
}
__ mov(a1, a0);
__ li(a0, Operand(Smi::FromInt(count_value)));
// Record position before stub call.
SetSourcePosition(expr->position());
@ -4336,29 +4337,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: {
VisitForAccumulatorValue(expr->right());
Condition cc = eq;
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
cc = eq;
break;
case Token::LT:
cc = lt;
break;
case Token::GT:
cc = gt;
break;
case Token::LTE:
cc = le;
break;
case Token::GTE:
cc = ge;
break;
case Token::IN:
case Token::INSTANCEOF:
default:
UNREACHABLE();
}
Condition cc = CompareIC::ComputeCondition(op);
__ mov(a0, result_register());
__ pop(a1);

View File

@ -1695,36 +1695,16 @@ Condition CompareIC::ComputeCondition(Token::Value op) {
}
void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
HandleScope scope;
Handle<Code> rewritten;
State previous_state = GetState();
State state = TargetState(previous_state, false, x, y);
if (state == GENERIC) {
CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, a1, a0);
rewritten = stub.GetCode();
} else {
ICCompareStub stub(op_, state);
if (state == KNOWN_OBJECTS) {
stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
}
rewritten = stub.GetCode();
}
set_target(*rewritten);
bool CompareIC::HasInlinedSmiCode(Address address) {
// The address of the instruction following the call.
Address andi_instruction_address =
address + Assembler::kCallTargetAddressOffset;
#ifdef DEBUG
if (FLAG_trace_ic) {
PrintF("[CompareIC (%s->%s)#%s]\n",
GetStateName(previous_state),
GetStateName(state),
Token::Name(op_));
}
#endif
// Activate inlined smi code.
if (previous_state == UNINITIALIZED) {
PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
}
// If the instruction following the call is not a andi at, rx, #yyy, nothing
// was inlined.
Instr instr = Assembler::instr_at(andi_instruction_address);
return Assembler::IsAndImmediate(instr) &&
Assembler::GetRt(instr) == (uint32_t)zero_reg.code();
}

View File

@ -229,7 +229,30 @@ bool LCodeGen::GenerateBody() {
}
if (emit_instructions) {
if (FLAG_code_comments) {
HValue* hydrogen = instr->hydrogen_value();
if (hydrogen != NULL) {
if (hydrogen->IsChange()) {
HValue* changed_value = HChange::cast(hydrogen)->value();
int use_id = 0;
const char* use_mnemo = "dead";
if (hydrogen->UseCount() >= 1) {
HValue* use_value = hydrogen->uses().value();
use_id = use_value->id();
use_mnemo = use_value->Mnemonic();
}
Comment(";;; @%d: %s. <of #%d %s for #%d %s>",
current_instruction_, instr->Mnemonic(),
changed_value->id(), changed_value->Mnemonic(),
use_id, use_mnemo);
} else {
Comment(";;; @%d: %s. <#%d>", current_instruction_,
instr->Mnemonic(), hydrogen->id());
}
} else {
Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
}
}
instr->CompileToNative(this);
}
}

View File

@ -1345,7 +1345,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
LInstruction* LChunkBuilder::DoCompareIDAndBranch(
HCompareIDAndBranch* instr) {
Representation r = instr->GetInputRepresentation();
Representation r = instr->representation();
if (r.IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
@ -2105,7 +2105,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
env->set_ast_id(instr->ast_id());
env->Drop(instr->pop_count());
for (int i = 0; i < instr->values()->length(); ++i) {
for (int i = instr->values()->length() - 1; i >= 0; --i) {
HValue* value = instr->values()->at(i);
if (instr->HasAssignedIndexAt(i)) {
env->Bind(instr->GetAssignedIndexAt(i), value);

View File

@ -616,7 +616,7 @@ class LCmpIDAndBranch: public LControlInstruction<2, 0> {
Token::Value op() const { return hydrogen()->token(); }
bool is_double() const {
return hydrogen()->GetInputRepresentation().IsDouble();
return hydrogen()->representation().IsDouble();
}
virtual void PrintDataTo(StringStream* stream);

View File

@ -2219,10 +2219,10 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
set_register(HI, static_cast<int32_t>(u64hilo >> 32));
break;
case DIV:
// Divide by zero was not checked in the configuration step - div and
// divu do not raise exceptions. On division by 0, the result will
// be UNPREDICTABLE.
if (rt != 0) {
// Divide by zero and overflow was not checked in the configuration
// step - div and divu do not raise exceptions. On division by 0 and
// on overflow (INT_MIN/-1), the result will be UNPREDICTABLE.
if (rt != 0 && !(rs == INT_MIN && rt == -1)) {
set_register(LO, rs / rt);
set_register(HI, rs % rt);
}