update V8 to r5532 as required by WebKit r68651
Change-Id: I5f75eeffbf64b30dd5080348528d277f293490ad
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index be9aa92..1c4fd60 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -69,13 +69,13 @@
//
// Core register
struct Register {
- bool is_valid() const { return 0 <= code_ && code_ < 16; }
- bool is(Register reg) const { return code_ == reg.code_; }
- int code() const {
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ bool is(Register reg) const { return code_ == reg.code_; }
+ int code() const {
ASSERT(is_valid());
return code_;
}
- int bit() const {
+ int bit() const {
ASSERT(is_valid());
return 1 << code_;
}
@@ -110,17 +110,17 @@
// Single word VFP register.
struct SwVfpRegister {
- bool is_valid() const { return 0 <= code_ && code_ < 32; }
- bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
- int code() const {
+ bool is_valid() const { return 0 <= code_ && code_ < 32; }
+ bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
+ int code() const {
ASSERT(is_valid());
return code_;
}
- int bit() const {
+ int bit() const {
ASSERT(is_valid());
return 1 << code_;
}
- void split_code(int* vm, int* m) const {
+ void split_code(int* vm, int* m) const {
ASSERT(is_valid());
*m = code_ & 0x1;
*vm = code_ >> 1;
@@ -133,31 +133,31 @@
// Double word VFP register.
struct DwVfpRegister {
// Supporting d0 to d15, can be later extended to d31.
- bool is_valid() const { return 0 <= code_ && code_ < 16; }
- bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
- SwVfpRegister low() const {
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
+ SwVfpRegister low() const {
SwVfpRegister reg;
reg.code_ = code_ * 2;
ASSERT(reg.is_valid());
return reg;
}
- SwVfpRegister high() const {
+ SwVfpRegister high() const {
SwVfpRegister reg;
reg.code_ = (code_ * 2) + 1;
ASSERT(reg.is_valid());
return reg;
}
- int code() const {
+ int code() const {
ASSERT(is_valid());
return code_;
}
- int bit() const {
+ int bit() const {
ASSERT(is_valid());
return 1 << code_;
}
- void split_code(int* vm, int* m) const {
+ void split_code(int* vm, int* m) const {
ASSERT(is_valid());
*m = (code_ & 0x10) >> 4;
*vm = code_ & 0x0F;
@@ -222,13 +222,13 @@
// Coprocessor register
struct CRegister {
- bool is_valid() const { return 0 <= code_ && code_ < 16; }
- bool is(CRegister creg) const { return code_ == creg.code_; }
- int code() const {
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ bool is(CRegister creg) const { return code_ == creg.code_; }
+ int code() const {
ASSERT(is_valid());
return code_;
}
- int bit() const {
+ int bit() const {
ASSERT(is_valid());
return 1 << code_;
}
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 8b21558..cf2f426 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -521,7 +521,11 @@
static void Generate_JSConstructStubHelper(MacroAssembler* masm,
- bool is_api_function) {
+ bool is_api_function,
+ bool count_constructions) {
+ // Should never count constructions for api objects.
+ ASSERT(!is_api_function || !count_constructions);
+
// Enter a construct frame.
__ EnterConstructFrame();
@@ -530,9 +534,6 @@
__ push(r0); // Smi-tagged arguments count.
__ push(r1); // Constructor function.
- // Use r7 for holding undefined which is used in several places below.
- __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
-
// Try to allocate the object without transitioning into C code. If any of the
// preconditions is not met, the code bails out to the runtime call.
Label rt_call, allocated;
@@ -549,7 +550,6 @@
// Load the initial map and verify that it is in fact a map.
// r1: constructor function
- // r7: undefined value
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
__ tst(r2, Operand(kSmiTagMask));
__ b(eq, &rt_call);
@@ -561,14 +561,35 @@
// instance type would be JS_FUNCTION_TYPE.
// r1: constructor function
// r2: initial map
- // r7: undefined value
__ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
__ b(eq, &rt_call);
+ if (count_constructions) {
+ Label allocate;
+ // Decrease generous allocation count.
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ MemOperand constructor_count =
+ FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset);
+ __ ldrb(r4, constructor_count);
+ __ sub(r4, r4, Operand(1), SetCC);
+ __ strb(r4, constructor_count);
+ __ b(ne, &allocate);
+
+ __ Push(r1, r2);
+
+ __ push(r1); // constructor
+ // The call will replace the stub, so the countdown is only done once.
+ __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
+
+ __ pop(r2);
+ __ pop(r1);
+
+ __ bind(&allocate);
+ }
+
// Now allocate the JSObject on the heap.
// r1: constructor function
// r2: initial map
- // r7: undefined value
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
__ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
@@ -578,7 +599,6 @@
// r2: initial map
// r3: object size
// r4: JSObject (not tagged)
- // r7: undefined value
__ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
__ mov(r5, r4);
ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
@@ -588,16 +608,21 @@
ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
__ str(r6, MemOperand(r5, kPointerSize, PostIndex));
- // Fill all the in-object properties with undefined.
+ // Fill all the in-object properties with the appropriate filler.
// r1: constructor function
// r2: initial map
// r3: object size (in words)
// r4: JSObject (not tagged)
// r5: First in-object property of JSObject (not tagged)
- // r7: undefined value
__ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
{ Label loop, entry;
+ if (count_constructions) {
+ // To allow for truncation.
+ __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
+ } else {
+ __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+ }
__ b(&entry);
__ bind(&loop);
__ str(r7, MemOperand(r5, kPointerSize, PostIndex));
@@ -617,7 +642,6 @@
// r1: constructor function
// r4: JSObject
// r5: start of next object (not tagged)
- // r7: undefined value
__ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
// The field instance sizes contains both pre-allocated property fields and
// in-object properties.
@@ -637,7 +661,6 @@
// r3: number of elements in properties array
// r4: JSObject
// r5: start of next object
- // r7: undefined value
__ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
__ AllocateInNewSpace(
r0,
@@ -652,7 +675,6 @@
// r3: number of elements in properties array
// r4: JSObject
// r5: FixedArray (not tagged)
- // r7: undefined value
__ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
__ mov(r2, r5);
ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
@@ -667,10 +689,16 @@
// r3: number of elements in properties array
// r4: JSObject
// r5: FixedArray (not tagged)
- // r7: undefined
__ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
{ Label loop, entry;
+ if (count_constructions) {
+ __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+ } else if (FLAG_debug_code) {
+ __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
+ __ cmp(r7, r8);
+ __ Assert(eq, "Undefined value not loaded.");
+ }
__ b(&entry);
__ bind(&loop);
__ str(r7, MemOperand(r2, kPointerSize, PostIndex));
@@ -822,13 +850,18 @@
}
+void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
+ Generate_JSConstructStubHelper(masm, false, true);
+}
+
+
void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false);
+ Generate_JSConstructStubHelper(masm, false, false);
}
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, true);
+ Generate_JSConstructStubHelper(masm, true, false);
}
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index fa93030..8f801cf 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -930,6 +930,24 @@
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles, lhs_not_nan;
+ if (include_smi_compare_) {
+ Label not_two_smis, smi_done;
+ __ orr(r2, r1, r0);
+ __ tst(r2, Operand(kSmiTagMask));
+ __ b(ne, ¬_two_smis);
+ __ sub(r0, r1, r0);
+ __ b(vc, &smi_done);
+ // Correct the sign in case of overflow.
+ __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
+ __ bind(&smi_done);
+ __ Ret();
+ __ bind(¬_two_smis);
+ } else if (FLAG_debug_code) {
+ __ orr(r2, r1, r0);
+ __ tst(r2, Operand(kSmiTagMask));
+ __ Assert(nz, "CompareStub: unexpected smi operands.");
+ }
+
// 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.
@@ -2288,7 +2306,7 @@
__ push(r0);
__ TailCallRuntime(Runtime::kStackGuard, 1, 1);
- __ StubReturn(1);
+ __ Ret();
}
@@ -2299,32 +2317,37 @@
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
if (op_ == Token::SUB) {
- // Check whether the value is a smi.
- Label try_float;
- __ tst(r0, Operand(kSmiTagMask));
- __ b(ne, &try_float);
+ if (include_smi_code_) {
+ // Check whether the value is a smi.
+ Label try_float;
+ __ tst(r0, Operand(kSmiTagMask));
+ __ b(ne, &try_float);
- // Go slow case if the value of the expression is zero
- // to make sure that we switch between 0 and -0.
- if (negative_zero_ == kStrictNegativeZero) {
- // If we have to check for zero, then we can check for the max negative
- // smi while we are at it.
- __ bic(ip, r0, Operand(0x80000000), SetCC);
- __ b(eq, &slow);
- __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
- __ StubReturn(1);
- } else {
- // The value of the expression is a smi and 0 is OK for -0. Try
- // optimistic subtraction '0 - value'.
- __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
- __ StubReturn(1, vc);
- // We don't have to reverse the optimistic neg since the only case
- // where we fall through is the minimum negative Smi, which is the case
- // where the neg leaves the register unchanged.
- __ jmp(&slow); // Go slow on max negative Smi.
+ // Go slow case if the value of the expression is zero
+ // to make sure that we switch between 0 and -0.
+ if (negative_zero_ == kStrictNegativeZero) {
+ // If we have to check for zero, then we can check for the max negative
+ // smi while we are at it.
+ __ bic(ip, r0, Operand(0x80000000), SetCC);
+ __ b(eq, &slow);
+ __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
+ __ Ret();
+ } else {
+ // The value of the expression is a smi and 0 is OK for -0. Try
+ // optimistic subtraction '0 - value'.
+ __ rsb(r0, r0, Operand(0, RelocInfo::NONE), SetCC);
+ __ Ret(vc);
+ // We don't have to reverse the optimistic neg since the only case
+ // where we fall through is the minimum negative Smi, which is the case
+ // where the neg leaves the register unchanged.
+ __ jmp(&slow); // Go slow on max negative Smi.
+ }
+ __ bind(&try_float);
+ } else if (FLAG_debug_code) {
+ __ tst(r0, Operand(kSmiTagMask));
+ __ Assert(ne, "Unexpected smi operand.");
}
- __ bind(&try_float);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
__ cmp(r1, heap_number_map);
@@ -2344,6 +2367,19 @@
__ mov(r0, Operand(r1));
}
} else if (op_ == Token::BIT_NOT) {
+ if (include_smi_code_) {
+ Label non_smi;
+ __ BranchOnNotSmi(r0, &non_smi);
+ __ mvn(r0, Operand(r0));
+ // Bit-clear inverted smi-tag.
+ __ bic(r0, r0, Operand(kSmiTagMask));
+ __ Ret();
+ __ bind(&non_smi);
+ } else if (FLAG_debug_code) {
+ __ tst(r0, Operand(kSmiTagMask));
+ __ Assert(ne, "Unexpected smi operand.");
+ }
+
// Check if the operand is a heap number.
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
@@ -2391,7 +2427,7 @@
}
__ bind(&done);
- __ StubReturn(1);
+ __ Ret();
// Handle the slow case by jumping to the JavaScript builtin.
__ bind(&slow);
@@ -3499,6 +3535,11 @@
include_number_compare_name = "_NO_NUMBER";
}
+ const char* include_smi_compare_name = "";
+ if (!include_smi_compare_) {
+ include_smi_compare_name = "_NO_SMI";
+ }
+
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
"CompareStub_%s%s%s%s%s%s",
cc_name,
@@ -3506,7 +3547,8 @@
rhs_name,
strict_name,
never_nan_nan_name,
- include_number_compare_name);
+ include_number_compare_name,
+ include_smi_compare_name);
return name_;
}
@@ -3522,7 +3564,8 @@
| RegisterField::encode(lhs_.is(r0))
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
- | IncludeNumberCompareField::encode(include_number_compare_);
+ | IncludeNumberCompareField::encode(include_number_compare_)
+ | IncludeSmiCompareField::encode(include_smi_compare_);
}
@@ -4144,17 +4187,21 @@
// Check bounds and smi-ness.
- __ ldr(r7, MemOperand(sp, kToOffset));
- __ ldr(r6, MemOperand(sp, kFromOffset));
+ Register to = r6;
+ Register from = r7;
+ __ Ldrd(to, from, MemOperand(sp, kToOffset));
+ STATIC_ASSERT(kFromOffset == kToOffset + 4);
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
// I.e., arithmetic shift right by one un-smi-tags.
- __ mov(r2, Operand(r7, ASR, 1), SetCC);
- __ mov(r3, Operand(r6, ASR, 1), SetCC, cc);
- // If either r2 or r6 had the smi tag bit set, then carry is set now.
+ __ mov(r2, Operand(to, ASR, 1), SetCC);
+ __ mov(r3, Operand(from, ASR, 1), SetCC, cc);
+ // If either to or from had the smi tag bit set, then carry is set now.
__ b(cs, &runtime); // Either "from" or "to" is not a smi.
__ b(mi, &runtime); // From is negative.
+ // Both to and from are smis.
+
__ sub(r2, r2, Operand(r3), SetCC);
__ b(mi, &runtime); // Fail if from > to.
// Special handling of sub-strings of length 1 and 2. One character strings
@@ -4165,8 +4212,8 @@
// r2: length
// r3: from index (untaged smi)
- // r6: from (smi)
- // r7: to (smi)
+ // r6 (a.k.a. to): to (smi)
+ // r7 (a.k.a. from): from offset (smi)
// Make sure first argument is a sequential (or flat) string.
__ ldr(r5, MemOperand(sp, kStringOffset));
@@ -4178,10 +4225,10 @@
// r1: instance type
// r2: length
- // r3: from index (untaged smi)
+ // r3: from index (untagged smi)
// r5: string
- // r6: from (smi)
- // r7: to (smi)
+ // r6 (a.k.a. to): to (smi)
+ // r7 (a.k.a. from): from offset (smi)
Label seq_string;
__ and_(r4, r1, Operand(kStringRepresentationMask));
STATIC_ASSERT(kSeqStringTag < kConsStringTag);
@@ -4207,17 +4254,18 @@
// r2: length
// r3: from index (untaged smi)
// r5: string
- // r6: from (smi)
- // r7: to (smi)
+ // r6 (a.k.a. to): to (smi)
+ // r7 (a.k.a. from): from offset (smi)
__ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
- __ cmp(r4, Operand(r7));
+ __ cmp(r4, Operand(to));
__ b(lt, &runtime); // Fail if to > length.
+ to = no_reg;
// r1: instance type.
// r2: result string length.
// r3: from index (untaged smi)
// r5: string.
- // r6: from offset (smi)
+ // r7 (a.k.a. from): from offset (smi)
// Check for flat ascii string.
Label non_ascii_flat;
__ tst(r1, Operand(kStringEncodingMask));
@@ -4259,12 +4307,12 @@
// r0: result string.
// r2: result string length.
// r5: string.
- // r6: from offset (smi)
+ // r7 (a.k.a. from): from offset (smi)
// Locate first character of result.
__ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
// Locate 'from' character of string.
__ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
- __ add(r5, r5, Operand(r6, ASR, 1));
+ __ add(r5, r5, Operand(from, ASR, 1));
// r0: result string.
// r1: first character of result string.
@@ -4280,7 +4328,7 @@
__ bind(&non_ascii_flat);
// r2: result string length.
// r5: string.
- // r6: from offset (smi)
+ // r7 (a.k.a. from): from offset (smi)
// Check for flat two byte string.
// Allocate the result.
@@ -4292,18 +4340,19 @@
// Locate first character of result.
__ add(r1, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
// Locate 'from' character of string.
- __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+ __ add(r5, r5, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
// As "from" is a smi it is 2 times the value which matches the size of a two
// byte character.
- __ add(r5, r5, Operand(r6));
+ __ add(r5, r5, Operand(from));
+ from = no_reg;
// r0: result string.
// r1: first character of result.
// r2: result length.
// r5: first character of string to copy.
STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
- StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
- DEST_ALWAYS_ALIGNED);
+ StringHelper::GenerateCopyCharactersLong(
+ masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
__ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
__ add(sp, sp, Operand(3 * kPointerSize));
__ Ret();
@@ -4379,8 +4428,7 @@
// Stack frame on entry.
// sp[0]: right string
// sp[4]: left string
- __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // left
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // right
+ __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1.
Label not_same;
__ cmp(r0, r1);
@@ -4395,12 +4443,12 @@
__ bind(¬_same);
// Check that both objects are sequential ascii strings.
- __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime);
+ __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime);
// Compare flat ascii strings natively. Remove arguments from stack first.
__ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
__ add(sp, sp, Operand(2 * kPointerSize));
- GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5);
+ GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5);
// Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index f985fb4..d273e75 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -246,7 +246,7 @@
frame_->AssertIsSpilled();
for (int i = 0; i < scope()->num_parameters(); i++) {
Variable* par = scope()->parameter(i);
- Slot* slot = par->slot();
+ Slot* slot = par->AsSlot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
ASSERT(!scope()->is_global_scope()); // No params in global scope.
__ ldr(r1, frame_->ParameterAt(i));
@@ -270,7 +270,7 @@
// Initialize ThisFunction reference if present.
if (scope()->is_function_scope() && scope()->function() != NULL) {
frame_->EmitPushRoot(Heap::kTheHoleValueRootIndex);
- StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
+ StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT);
}
// Initialize the function return target after the locals are set
@@ -608,24 +608,24 @@
frame_->EmitPush(r0);
}
- Variable* arguments = scope()->arguments()->var();
- Variable* shadow = scope()->arguments_shadow()->var();
- ASSERT(arguments != NULL && arguments->slot() != NULL);
- ASSERT(shadow != NULL && shadow->slot() != NULL);
+ Variable* arguments = scope()->arguments();
+ Variable* shadow = scope()->arguments_shadow();
+ ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
+ ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
JumpTarget done;
if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
// We have to skip storing into the arguments slot if it has
// already been written to. This can happen if the a function
// has a local variable named 'arguments'.
- LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
+ LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF);
Register arguments = frame_->PopToRegister();
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(arguments, ip);
done.Branch(ne);
}
- StoreToSlot(arguments->slot(), NOT_CONST_INIT);
+ StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
- StoreToSlot(shadow->slot(), NOT_CONST_INIT);
+ StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
}
@@ -641,10 +641,10 @@
Property property(&global, &key, RelocInfo::kNoPosition);
Reference ref(this, &property);
ref.GetValue();
- } else if (variable != NULL && variable->slot() != NULL) {
+ } else if (variable != NULL && variable->AsSlot() != NULL) {
// For a variable that rewrites to a slot, we signal it is the immediate
// subexpression of a typeof.
- LoadFromSlotCheckForArguments(variable->slot(), INSIDE_TYPEOF);
+ LoadFromSlotCheckForArguments(variable->AsSlot(), INSIDE_TYPEOF);
} else {
// Anything else can be handled normally.
Load(expr);
@@ -695,7 +695,7 @@
LoadGlobal();
ref->set_type(Reference::NAMED);
} else {
- ASSERT(var->slot() != NULL);
+ ASSERT(var->AsSlot() != NULL);
ref->set_type(Reference::SLOT);
}
} else {
@@ -1651,7 +1651,7 @@
// Perform non-smi comparison by stub.
// CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
// We call with 0 args because there are 0 on the stack.
- CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs);
+ CompareStub stub(cc, strict, NO_SMI_COMPARE_IN_STUB, lhs, rhs);
frame_->CallStub(&stub, 0);
__ cmp(r0, Operand(0, RelocInfo::NONE));
exit.Jump();
@@ -1718,7 +1718,7 @@
// Load the receiver and the existing arguments object onto the
// expression stack. Avoid allocating the arguments object here.
Load(receiver);
- LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
+ LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF);
// At this point the top two stack elements are probably in registers
// since they were just loaded. Ensure they are in regs and get the
@@ -1950,7 +1950,7 @@
Comment cmnt(masm_, "[ Declaration");
Variable* var = node->proxy()->var();
ASSERT(var != NULL); // must have been resolved
- Slot* slot = var->slot();
+ Slot* slot = var->AsSlot();
// If it was not possible to allocate the variable at compile time,
// we need to "declare" it at runtime to make sure it actually
@@ -2480,8 +2480,8 @@
// the bottom check of the loop condition.
TypeInfoCodeGenState type_info_scope(this,
node->is_fast_smi_loop() ?
- node->loop_variable()->slot() :
- NULL,
+ node->loop_variable()->AsSlot() :
+ NULL,
TypeInfo::Smi());
// If there is no update statement, label the top of the loop with the
@@ -2794,8 +2794,8 @@
// Store the caught exception in the catch variable.
Variable* catch_var = node->catch_var()->var();
- ASSERT(catch_var != NULL && catch_var->slot() != NULL);
- StoreToSlot(catch_var->slot(), NOT_CONST_INIT);
+ ASSERT(catch_var != NULL && catch_var->AsSlot() != NULL);
+ StoreToSlot(catch_var->AsSlot(), NOT_CONST_INIT);
// Remove the exception from the stack.
frame_->Drop();
@@ -3420,7 +3420,7 @@
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
frame_->SpillAll();
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+ Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
@@ -3449,7 +3449,7 @@
// variables. Then load the argument from the arguments
// object using keyed load.
__ ldr(r0,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
+ ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
r1,
r2,
slow));
@@ -3735,7 +3735,7 @@
Comment cmnt(masm(), "[ Variable Assignment");
Variable* var = node->target()->AsVariableProxy()->AsVariable();
ASSERT(var != NULL);
- Slot* slot = var->slot();
+ Slot* slot = var->AsSlot();
ASSERT(slot != NULL);
// Evaluate the right-hand side.
@@ -4136,14 +4136,14 @@
// in generated code. If we succeed, there is no need to perform a
// context lookup in the runtime system.
JumpTarget done;
- if (var->slot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
- ASSERT(var->slot()->type() == Slot::LOOKUP);
+ if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ ASSERT(var->AsSlot()->type() == Slot::LOOKUP);
JumpTarget slow;
// Prepare the stack for the call to
// ResolvePossiblyDirectEvalNoLookup by pushing the loaded
// function, the first argument to the eval call and the
// receiver.
- LoadFromGlobalSlotCheckExtensions(var->slot(),
+ LoadFromGlobalSlotCheckExtensions(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow);
frame_->EmitPush(r0);
@@ -4225,8 +4225,8 @@
__ ldr(cp, frame_->Context());
frame_->EmitPush(r0);
- } else if (var != NULL && var->slot() != NULL &&
- var->slot()->type() == Slot::LOOKUP) {
+ } else if (var != NULL && var->AsSlot() != NULL &&
+ var->AsSlot()->type() == Slot::LOOKUP) {
// ----------------------------------
// JavaScript examples:
//
@@ -4244,7 +4244,7 @@
// Generate fast case for loading functions from slots that
// correspond to local/global variables or arguments unless they
// are shadowed by eval-introduced bindings.
- EmitDynamicLoadFromSlotFastCase(var->slot(),
+ EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow,
&done);
@@ -5928,7 +5928,7 @@
frame_->EmitPush(r0);
} else if (variable != NULL) {
- Slot* slot = variable->slot();
+ Slot* slot = variable->AsSlot();
if (variable->is_global()) {
LoadGlobal();
frame_->EmitPush(Operand(variable->name()));
@@ -5985,6 +5985,7 @@
GenericUnaryOpStub stub(
Token::SUB,
overwrite,
+ NO_UNARY_FLAGS,
no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
frame_->CallStub(&stub, 0);
frame_->EmitPush(r0); // r0 has result
@@ -6009,7 +6010,9 @@
not_smi_label.Bind();
frame_->SpillAll();
__ Move(r0, tos);
- GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
+ GenericUnaryOpStub stub(Token::BIT_NOT,
+ overwrite,
+ NO_UNARY_SMI_CODE_IN_STUB);
frame_->CallStub(&stub, 0);
frame_->EmitPush(r0);
@@ -6059,7 +6062,7 @@
bool is_const = (var != NULL && var->mode() == Variable::CONST);
bool is_slot = (var != NULL && var->mode() == Variable::VAR);
- if (!is_const && is_slot && type_info(var->slot()).IsSmi()) {
+ if (!is_const && is_slot && type_info(var->AsSlot()).IsSmi()) {
// The type info declares that this variable is always a Smi. That
// means it is a Smi both before and after the increment/decrement.
// Lets make use of that to make a very minimal count.
@@ -7204,7 +7207,7 @@
switch (type_) {
case SLOT: {
Comment cmnt(masm, "[ Load from Slot");
- Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+ Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot();
ASSERT(slot != NULL);
DupIfPersist();
cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
@@ -7248,7 +7251,7 @@
switch (type_) {
case SLOT: {
Comment cmnt(masm, "[ Store to Slot");
- Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
+ Slot* slot = expression_->AsVariableProxy()->AsVariable()->AsSlot();
cgen_->StoreToSlot(slot, init_state);
set_unloaded();
break;
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 162d97f..1483c0b 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -271,10 +271,6 @@
void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
- // If the name is an inline runtime function call return the number of
- // expected arguments. Otherwise return -1.
- static int InlineRuntimeCallArgumentsCount(Handle<String> name);
-
// Constants related to patching of inlined load/store.
static int GetInlinedKeyedLoadInstructionsAfterPatch() {
return FLAG_debug_code ? 32 : 13;
@@ -290,6 +286,12 @@
}
private:
+ // Type of a member function that generates inline code for a native function.
+ typedef void (CodeGenerator::*InlineFunctionGenerator)
+ (ZoneList<Expression*>*);
+
+ static const InlineFunctionGenerator kInlineFunctionGenerators[];
+
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
@@ -305,9 +307,9 @@
int NumberOfSlot(Slot* slot);
// State
- bool has_cc() const { return cc_reg_ != al; }
- JumpTarget* true_target() const { return state_->true_target(); }
- JumpTarget* false_target() const { return state_->false_target(); }
+ bool has_cc() const { return cc_reg_ != al; }
+ JumpTarget* true_target() const { return state_->true_target(); }
+ JumpTarget* false_target() const { return state_->false_target(); }
// Track loop nesting level.
int loop_nesting() const { return loop_nesting_; }
@@ -447,13 +449,9 @@
void Branch(bool if_true, JumpTarget* target);
void CheckStack();
- struct InlineRuntimeLUT {
- void (CodeGenerator::*method)(ZoneList<Expression*>*);
- const char* name;
- int nargs;
- };
+ static InlineFunctionGenerator FindInlineFunctionGenerator(
+ Runtime::FunctionId function_id);
- static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
bool CheckForInlineRuntimeCall(CallRuntime* node);
static Handle<Code> ComputeLazyCompile(int argc);
@@ -599,8 +597,6 @@
// Size of inlined write barriers generated by EmitNamedStore.
static int inlined_write_barrier_size_;
- static InlineRuntimeLUT kInlineRuntimeLUT[];
-
friend class VirtualFrame;
friend class JumpTarget;
friend class Reference;
diff --git a/src/arm/frames-arm.cc b/src/arm/frames-arm.cc
index 4743439..b0c0990 100644
--- a/src/arm/frames-arm.cc
+++ b/src/arm/frames-arm.cc
@@ -37,17 +37,8 @@
namespace internal {
-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
- if (fp == 0) return NONE;
- // Compute frame type and stack pointer.
- Address sp = fp + ExitFrameConstants::kSPOffset;
-
- // Fill in the state.
- state->sp = sp;
- state->fp = fp;
- state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- ASSERT(*state->pc_address != NULL);
- return EXIT;
+Address ExitFrame::ComputeStackPointer(Address fp) {
+ return fp + ExitFrameConstants::kSPOffset;
}
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 0f8f6d4..9fc0c09 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -100,7 +100,7 @@
// Copy any necessary parameters into the context.
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
- Slot* slot = scope()->parameter(i)->slot();
+ Slot* slot = scope()->parameter(i)->AsSlot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
@@ -118,7 +118,7 @@
}
}
- Variable* arguments = scope()->arguments()->AsVariable();
+ Variable* arguments = scope()->arguments();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
@@ -143,9 +143,8 @@
__ CallStub(&stub);
// Duplicate the value; move-to-slot operation might clobber registers.
__ mov(r3, r0);
- Move(arguments->slot(), r0, r1, r2);
- Slot* dot_arguments_slot =
- scope()->arguments_shadow()->AsVariable()->slot();
+ Move(arguments->AsSlot(), r0, r1, r2);
+ Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
Move(dot_arguments_slot, r3, r1, r2);
}
@@ -253,205 +252,202 @@
}
-void FullCodeGenerator::Apply(Expression::Context context, Register reg) {
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
+void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
+}
- case Expression::kEffect:
- // Nothing to do.
- break;
- case Expression::kValue:
- // Move value into place.
- switch (location_) {
- case kAccumulator:
- if (!reg.is(result_register())) __ mov(result_register(), reg);
- break;
- case kStack:
- __ push(reg);
- break;
- }
- break;
+void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
+ codegen()->Move(result_register(), slot);
+}
- case Expression::kTest:
- // For simplicity we always test the accumulator register.
- if (!reg.is(result_register())) __ mov(result_register(), reg);
- DoTest(true_label_, false_label_, fall_through_);
- break;
+
+void FullCodeGenerator::StackValueContext::Plug(Slot* slot) const {
+ codegen()->Move(result_register(), slot);
+ __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Slot* slot) const {
+ // For simplicity we always test the accumulator register.
+ codegen()->Move(result_register(), slot);
+ codegen()->DoTest(true_label_, false_label_, fall_through_);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+ Heap::RootListIndex index) const {
+ __ LoadRoot(result_register(), index);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+ Heap::RootListIndex index) const {
+ __ LoadRoot(result_register(), index);
+ __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
+ if (index == Heap::kUndefinedValueRootIndex ||
+ index == Heap::kNullValueRootIndex ||
+ index == Heap::kFalseValueRootIndex) {
+ __ b(false_label_);
+ } else if (index == Heap::kTrueValueRootIndex) {
+ __ b(true_label_);
+ } else {
+ __ LoadRoot(result_register(), index);
+ codegen()->DoTest(true_label_, false_label_, fall_through_);
}
}
-void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) {
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Nothing to do.
- break;
- case Expression::kValue:
- case Expression::kTest:
- // On ARM we have to move the value into a register to do anything
- // with it.
- Move(result_register(), slot);
- Apply(context, result_register());
- break;
+void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+ Handle<Object> lit) const {
+ __ mov(result_register(), Operand(lit));
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
+ // Immediates can be pushed directly.
+ __ mov(result_register(), Operand(lit));
+ __ push(result_register());
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
+ ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
+ if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
+ __ b(false_label_);
+ } else if (lit->IsTrue() || lit->IsJSObject()) {
+ __ b(true_label_);
+ } else if (lit->IsString()) {
+ if (String::cast(*lit)->length() == 0) {
+ __ b(false_label_);
+ } else {
+ __ b(true_label_);
+ }
+ } else if (lit->IsSmi()) {
+ if (Smi::cast(*lit)->value() == 0) {
+ __ b(false_label_);
+ } else {
+ __ b(true_label_);
+ }
+ } else {
+ // For simplicity we always test the accumulator register.
+ __ mov(result_register(), Operand(lit));
+ codegen()->DoTest(true_label_, false_label_, fall_through_);
}
}
-void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) {
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- break;
- // Nothing to do.
- case Expression::kValue:
- case Expression::kTest:
- // On ARM we have to move the value into a register to do anything
- // with it.
- __ mov(result_register(), Operand(lit->handle()));
- Apply(context, result_register());
- break;
- }
-}
-
-
-void FullCodeGenerator::ApplyTOS(Expression::Context context) {
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
-
- case Expression::kEffect:
- __ Drop(1);
- break;
-
- case Expression::kValue:
- switch (location_) {
- case kAccumulator:
- __ pop(result_register());
- break;
- case kStack:
- break;
- }
- break;
-
- case Expression::kTest:
- __ pop(result_register());
- DoTest(true_label_, false_label_, fall_through_);
- break;
- }
-}
-
-
-void FullCodeGenerator::DropAndApply(int count,
- Expression::Context context,
- Register reg) {
+void FullCodeGenerator::EffectContext::DropAndPlug(int count,
+ Register reg) const {
ASSERT(count > 0);
- ASSERT(!reg.is(sp));
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
-
- case Expression::kEffect:
- __ Drop(count);
- break;
-
- case Expression::kValue:
- switch (location_) {
- case kAccumulator:
- __ Drop(count);
- if (!reg.is(result_register())) __ mov(result_register(), reg);
- break;
- case kStack:
- if (count > 1) __ Drop(count - 1);
- __ str(reg, MemOperand(sp));
- break;
- }
- break;
-
- case Expression::kTest:
- __ Drop(count);
- if (!reg.is(result_register())) __ mov(result_register(), reg);
- DoTest(true_label_, false_label_, fall_through_);
- break;
- }
+ __ Drop(count);
}
-void FullCodeGenerator::Apply(Expression::Context context,
- Label* materialize_true,
- Label* materialize_false) {
- switch (context) {
- case Expression::kUninitialized:
-
- case Expression::kEffect:
- ASSERT_EQ(materialize_true, materialize_false);
- __ bind(materialize_true);
- break;
-
- case Expression::kValue: {
- Label done;
- switch (location_) {
- case kAccumulator:
- __ bind(materialize_true);
- __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
- __ jmp(&done);
- __ bind(materialize_false);
- __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
- break;
- case kStack:
- __ bind(materialize_true);
- __ LoadRoot(ip, Heap::kTrueValueRootIndex);
- __ push(ip);
- __ jmp(&done);
- __ bind(materialize_false);
- __ LoadRoot(ip, Heap::kFalseValueRootIndex);
- __ push(ip);
- break;
- }
- __ bind(&done);
- break;
- }
-
- case Expression::kTest:
- break;
- }
+void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
+ int count,
+ Register reg) const {
+ ASSERT(count > 0);
+ __ Drop(count);
+ __ Move(result_register(), reg);
}
-// Convert constant control flow (true or false) to the result expected for
-// a given expression context.
-void FullCodeGenerator::Apply(Expression::Context context, bool flag) {
- switch (context) {
- case Expression::kUninitialized:
- UNREACHABLE();
- break;
- case Expression::kEffect:
- break;
- case Expression::kValue: {
- Heap::RootListIndex value_root_index =
- flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
- switch (location_) {
- case kAccumulator:
- __ LoadRoot(result_register(), value_root_index);
- break;
- case kStack:
- __ LoadRoot(ip, value_root_index);
- __ push(ip);
- break;
- }
- break;
- }
- case Expression::kTest:
- if (flag) {
- if (true_label_ != fall_through_) __ b(true_label_);
- } else {
- if (false_label_ != fall_through_) __ b(false_label_);
- }
- break;
+void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
+ Register reg) const {
+ ASSERT(count > 0);
+ if (count > 1) __ Drop(count - 1);
+ __ str(reg, MemOperand(sp, 0));
+}
+
+
+void FullCodeGenerator::TestContext::DropAndPlug(int count,
+ Register reg) const {
+ ASSERT(count > 0);
+ // For simplicity we always test the accumulator register.
+ __ Drop(count);
+ __ Move(result_register(), reg);
+ codegen()->DoTest(true_label_, false_label_, fall_through_);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
+ Label* materialize_false) const {
+ ASSERT_EQ(materialize_true, materialize_false);
+ __ bind(materialize_true);
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(
+ Label* materialize_true,
+ Label* materialize_false) const {
+ Label done;
+ __ bind(materialize_true);
+ __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
+ __ jmp(&done);
+ __ bind(materialize_false);
+ __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
+ __ bind(&done);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(
+ Label* materialize_true,
+ Label* materialize_false) const {
+ Label done;
+ __ bind(materialize_true);
+ __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+ __ push(ip);
+ __ jmp(&done);
+ __ bind(materialize_false);
+ __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+ __ push(ip);
+ __ bind(&done);
+}
+
+
+void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
+ Label* materialize_false) const {
+ ASSERT(materialize_false == false_label_);
+ ASSERT(materialize_true == true_label_);
+}
+
+
+void FullCodeGenerator::EffectContext::Plug(bool flag) const {
+}
+
+
+void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
+ Heap::RootListIndex value_root_index =
+ flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
+ __ LoadRoot(result_register(), value_root_index);
+}
+
+
+void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
+ Heap::RootListIndex value_root_index =
+ flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
+ __ LoadRoot(ip, value_root_index);
+ __ push(ip);
+}
+
+
+void FullCodeGenerator::TestContext::Plug(bool flag) const {
+ if (flag) {
+ if (true_label_ != fall_through_) __ b(true_label_);
+ } else {
+ if (false_label_ != fall_through_) __ b(false_label_);
}
}
@@ -533,7 +529,7 @@
FunctionLiteral* function) {
Comment cmnt(masm_, "[ Declaration");
ASSERT(variable != NULL); // Must have been resolved.
- Slot* slot = variable->slot();
+ Slot* slot = variable->AsSlot();
Property* prop = variable->AsProperty();
if (slot != NULL) {
@@ -544,7 +540,7 @@
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ str(ip, MemOperand(fp, SlotOffset(slot)));
} else if (function != NULL) {
- VisitForValue(function, kAccumulator);
+ VisitForAccumulatorValue(function);
__ str(result_register(), MemOperand(fp, SlotOffset(slot)));
}
break;
@@ -566,7 +562,7 @@
__ str(ip, ContextOperand(cp, slot->index()));
// No write barrier since the_hole_value is in old space.
} else if (function != NULL) {
- VisitForValue(function, kAccumulator);
+ VisitForAccumulatorValue(function);
__ str(result_register(), ContextOperand(cp, slot->index()));
int offset = Context::SlotOffset(slot->index());
// We know that we have written a function, which is not a smi.
@@ -593,7 +589,7 @@
} else if (function != NULL) {
__ Push(cp, r2, r1);
// Push initial value for function declaration.
- VisitForValue(function, kStack);
+ VisitForStackValue(function);
} else {
__ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
__ Push(cp, r2, r1, r0);
@@ -607,20 +603,20 @@
if (function != NULL || mode == Variable::CONST) {
// We are declaring a function or constant that rewrites to a
// property. Use (keyed) IC to set the initial value.
- VisitForValue(prop->obj(), kStack);
+ VisitForStackValue(prop->obj());
if (function != NULL) {
- VisitForValue(prop->key(), kStack);
- VisitForValue(function, kAccumulator);
+ VisitForStackValue(prop->key());
+ VisitForAccumulatorValue(function);
__ pop(r1); // Key.
} else {
- VisitForValue(prop->key(), kAccumulator);
+ VisitForAccumulatorValue(prop->key());
__ mov(r1, result_register()); // Key.
__ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
}
__ pop(r2); // Receiver.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
// Value in r0 is ignored (declarations are statements).
}
}
@@ -648,7 +644,7 @@
Breakable nested_statement(this, stmt);
SetStatementPosition(stmt);
// Keep the switch value on the stack until a case matches.
- VisitForValue(stmt->tag(), kStack);
+ VisitForStackValue(stmt->tag());
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@@ -668,11 +664,12 @@
next_test.Unuse();
// Compile the label expression.
- VisitForValue(clause->label(), kAccumulator);
+ VisitForAccumulatorValue(clause->label());
// Perform the comparison as if via '==='.
__ ldr(r1, MemOperand(sp, 0)); // Switch value.
- if (ShouldInlineSmiCase(Token::EQ_STRICT)) {
+ bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
+ if (inline_smi_code) {
Label slow_case;
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
@@ -684,7 +681,10 @@
__ bind(&slow_case);
}
- CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
+ CompareFlags flags = inline_smi_code
+ ? NO_SMI_COMPARE_IN_STUB
+ : NO_COMPARE_FLAGS;
+ CompareStub stub(eq, true, flags, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0, RelocInfo::NONE));
__ b(ne, &next_test);
@@ -725,7 +725,7 @@
// Get the object to enumerate over. Both SpiderMonkey and JSC
// ignore null and undefined in contrast to the specification; see
// ECMA-262 section 12.6.4.
- VisitForValue(stmt->enumerable(), kAccumulator);
+ VisitForAccumulatorValue(stmt->enumerable());
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
__ b(eq, &exit);
@@ -868,13 +868,13 @@
__ Push(cp, r0);
__ CallRuntime(Runtime::kNewClosure, 2);
}
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
Comment cmnt(masm_, "[ VariableProxy");
- EmitVariableLoad(expr->var(), context_);
+ EmitVariableLoad(expr->var());
}
@@ -923,7 +923,7 @@
EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
__ jmp(done);
} else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
- Slot* potential_slot = slot->var()->local_if_not_shadowed()->slot();
+ Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
if (potential_slot != NULL) {
// Generate fast case for locals that rewrite to slots.
@@ -948,11 +948,11 @@
// variables. Then load the argument from the arguments
// object using keyed load.
__ ldr(r1,
- ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
+ ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
slow));
__ mov(r0, Operand(key_literal->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
__ jmp(done);
}
}
@@ -1018,16 +1018,15 @@
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- __ Call(ic, mode);
+ EmitCallIC(ic, mode);
}
-void FullCodeGenerator::EmitVariableLoad(Variable* var,
- Expression::Context context) {
+void FullCodeGenerator::EmitVariableLoad(Variable* var) {
// Four cases: non-this global variables, lookup slots, all other
// types of slots, and parameters that rewrite to explicit property
// accesses on the arguments object.
- Slot* slot = var->slot();
+ Slot* slot = var->AsSlot();
Property* property = var->AsProperty();
if (var->is_global() && !var->is_this()) {
@@ -1037,8 +1036,8 @@
__ ldr(r0, CodeGenerator::GlobalObject());
__ mov(r2, Operand(var->name()));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
- Apply(context, r0);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ context()->Plug(r0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Label done, slow;
@@ -1054,24 +1053,24 @@
__ CallRuntime(Runtime::kLoadContextSlot, 2);
__ bind(&done);
- Apply(context, r0);
+ context()->Plug(r0);
} else if (slot != NULL) {
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
? "Context slot"
: "Stack slot");
if (var->mode() == Variable::CONST) {
- // Constants may be the hole value if they have not been initialized.
- // Unhole them.
- MemOperand slot_operand = EmitSlotSearch(slot, r0);
- __ ldr(r0, slot_operand);
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
- __ cmp(r0, ip);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
- Apply(context, r0);
- } else {
- Apply(context, slot);
- }
+ // Constants may be the hole value if they have not been initialized.
+ // Unhole them.
+ MemOperand slot_operand = EmitSlotSearch(slot, r0);
+ __ ldr(r0, slot_operand);
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(r0, ip);
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+ context()->Plug(r0);
+ } else {
+ context()->Plug(slot);
+ }
} else {
Comment cmnt(masm_, "Rewritten parameter");
ASSERT_NOT_NULL(property);
@@ -1080,7 +1079,7 @@
// Assert that the object is in a slot.
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
ASSERT_NOT_NULL(object_var);
- Slot* object_slot = object_var->slot();
+ Slot* object_slot = object_var->AsSlot();
ASSERT_NOT_NULL(object_slot);
// Load the object.
@@ -1096,8 +1095,8 @@
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
- Apply(context, r0);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
+ context()->Plug(r0);
}
}
@@ -1141,7 +1140,7 @@
// r2: temp.
__ pop(r1);
__ CopyFields(r0, r1, r2.bit(), size / kPointerSize);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -1181,11 +1180,11 @@
// Fall through.
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
- VisitForValue(value, kAccumulator);
+ VisitForAccumulatorValue(value);
__ mov(r2, Operand(key->handle()));
__ ldr(r1, MemOperand(sp));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
break;
}
// Fall through.
@@ -1193,8 +1192,8 @@
// Duplicate receiver on stack.
__ ldr(r0, MemOperand(sp));
__ push(r0);
- VisitForValue(key, kStack);
- VisitForValue(value, kStack);
+ VisitForStackValue(key);
+ VisitForStackValue(value);
__ CallRuntime(Runtime::kSetProperty, 3);
break;
case ObjectLiteral::Property::GETTER:
@@ -1202,21 +1201,21 @@
// Duplicate receiver on stack.
__ ldr(r0, MemOperand(sp));
__ push(r0);
- VisitForValue(key, kStack);
+ VisitForStackValue(key);
__ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
__ push(r1);
- VisitForValue(value, kStack);
+ VisitForStackValue(value);
__ CallRuntime(Runtime::kDefineAccessor, 4);
break;
}
}
if (result_saved) {
- ApplyTOS(context_);
+ context()->PlugTOS();
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
}
@@ -1264,7 +1263,7 @@
__ push(r0);
result_saved = true;
}
- VisitForValue(subexpr, kAccumulator);
+ VisitForAccumulatorValue(subexpr);
// Store the subexpression value in the array's elements.
__ ldr(r1, MemOperand(sp)); // Copy of array literal.
@@ -1278,9 +1277,9 @@
}
if (result_saved) {
- ApplyTOS(context_);
+ context()->PlugTOS();
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
}
@@ -1313,39 +1312,38 @@
case NAMED_PROPERTY:
if (expr->is_compound()) {
// We need the receiver both on the stack and in the accumulator.
- VisitForValue(property->obj(), kAccumulator);
+ VisitForAccumulatorValue(property->obj());
__ push(result_register());
} else {
- VisitForValue(property->obj(), kStack);
+ VisitForStackValue(property->obj());
}
break;
case KEYED_PROPERTY:
if (expr->is_compound()) {
- VisitForValue(property->obj(), kStack);
- VisitForValue(property->key(), kAccumulator);
+ VisitForStackValue(property->obj());
+ VisitForAccumulatorValue(property->key());
__ ldr(r1, MemOperand(sp, 0));
__ push(r0);
} else {
- VisitForValue(property->obj(), kStack);
- VisitForValue(property->key(), kStack);
+ VisitForStackValue(property->obj());
+ VisitForStackValue(property->key());
}
break;
}
if (expr->is_compound()) {
- Location saved_location = location_;
- location_ = kAccumulator;
- switch (assign_type) {
- case VARIABLE:
- EmitVariableLoad(expr->target()->AsVariableProxy()->var(),
- Expression::kValue);
- break;
- case NAMED_PROPERTY:
- EmitNamedPropertyLoad(property);
- break;
- case KEYED_PROPERTY:
- EmitKeyedPropertyLoad(property);
- break;
+ { AccumulatorValueContext context(this);
+ switch (assign_type) {
+ case VARIABLE:
+ EmitVariableLoad(expr->target()->AsVariableProxy()->var());
+ break;
+ case NAMED_PROPERTY:
+ EmitNamedPropertyLoad(property);
+ break;
+ case KEYED_PROPERTY:
+ EmitKeyedPropertyLoad(property);
+ break;
+ }
}
Token::Value op = expr->binary_op();
@@ -1355,28 +1353,26 @@
ASSERT(constant == kRightConstant || constant == kNoConstants);
if (constant == kNoConstants) {
__ push(r0); // Left operand goes on the stack.
- VisitForValue(expr->value(), kAccumulator);
+ VisitForAccumulatorValue(expr->value());
}
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
? OVERWRITE_RIGHT
: NO_OVERWRITE;
SetSourcePosition(expr->position() + 1);
+ AccumulatorValueContext context(this);
if (ShouldInlineSmiCase(op)) {
EmitInlineSmiBinaryOp(expr,
op,
- Expression::kValue,
mode,
expr->target(),
expr->value(),
constant);
} else {
- EmitBinaryOp(op, Expression::kValue, mode);
+ EmitBinaryOp(op, mode);
}
- location_ = saved_location;
-
} else {
- VisitForValue(expr->value(), kAccumulator);
+ VisitForAccumulatorValue(expr->value());
}
// Record source position before possible IC call.
@@ -1386,8 +1382,7 @@
switch (assign_type) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
- expr->op(),
- context_);
+ expr->op());
break;
case NAMED_PROPERTY:
EmitNamedPropertyAssignment(expr);
@@ -1405,7 +1400,7 @@
__ mov(r2, Operand(key->handle()));
// Call load IC. It has arguments receiver and property name r0 and r2.
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
}
@@ -1413,29 +1408,27 @@
SetSourcePosition(prop->position());
// Call keyed load IC. It has arguments key and receiver in r0 and r1.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
}
void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
Token::Value op,
- Expression::Context context,
OverwriteMode mode,
Expression* left,
Expression* right,
ConstantOperand constant) {
ASSERT(constant == kNoConstants); // Only handled case.
- EmitBinaryOp(op, context, mode);
+ EmitBinaryOp(op, mode);
}
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
- Expression::Context context,
OverwriteMode mode) {
__ pop(r1);
GenericBinaryOpStub stub(op, mode, r1, r0);
__ CallStub(&stub);
- Apply(context, r0);
+ context()->Plug(r0);
}
@@ -1461,28 +1454,29 @@
switch (assign_type) {
case VARIABLE: {
Variable* var = expr->AsVariableProxy()->var();
- EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect);
+ EffectContext context(this);
+ EmitVariableAssignment(var, Token::ASSIGN);
break;
}
case NAMED_PROPERTY: {
__ push(r0); // Preserve value.
- VisitForValue(prop->obj(), kAccumulator);
+ VisitForAccumulatorValue(prop->obj());
__ mov(r1, r0);
__ pop(r0); // Restore value.
__ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
break;
}
case KEYED_PROPERTY: {
__ push(r0); // Preserve value.
- VisitForValue(prop->obj(), kStack);
- VisitForValue(prop->key(), kAccumulator);
+ VisitForStackValue(prop->obj());
+ VisitForAccumulatorValue(prop->key());
__ mov(r1, r0);
__ pop(r2);
__ pop(r0); // Restore value.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
break;
}
}
@@ -1490,12 +1484,11 @@
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
- Token::Value op,
- Expression::Context context) {
+ Token::Value op) {
// Left-hand sides that rewrite to explicit property accesses do not reach
// here.
ASSERT(var != NULL);
- ASSERT(var->is_global() || var->slot() != NULL);
+ ASSERT(var->is_global() || var->AsSlot() != NULL);
if (var->is_global()) {
ASSERT(!var->is_this());
@@ -1505,13 +1498,13 @@
__ mov(r2, Operand(var->name()));
__ ldr(r1, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
} else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) {
// Perform the assignment for non-const variables and for initialization
// of const variables. Const assignments are simply skipped.
Label done;
- Slot* slot = var->slot();
+ Slot* slot = var->AsSlot();
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
@@ -1561,7 +1554,7 @@
__ bind(&done);
}
- Apply(context, result_register());
+ context()->Plug(result_register());
}
@@ -1594,7 +1587,7 @@
}
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
// If the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) {
@@ -1604,9 +1597,9 @@
__ push(ip);
__ CallRuntime(Runtime::kToFastProperties, 1);
__ pop(r0);
- DropAndApply(1, context_, r0);
+ context()->DropAndPlug(1, r0);
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
}
@@ -1638,7 +1631,7 @@
}
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
// If the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) {
@@ -1648,9 +1641,9 @@
__ push(ip);
__ CallRuntime(Runtime::kToFastProperties, 1);
__ pop(r0);
- DropAndApply(1, context_, r0);
+ context()->DropAndPlug(1, r0);
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
}
@@ -1660,16 +1653,15 @@
Expression* key = expr->key();
if (key->IsPropertyName()) {
- VisitForValue(expr->obj(), kAccumulator);
+ VisitForAccumulatorValue(expr->obj());
EmitNamedPropertyLoad(expr);
- Apply(context_, r0);
} else {
- VisitForValue(expr->obj(), kStack);
- VisitForValue(expr->key(), kAccumulator);
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
__ pop(r1);
EmitKeyedPropertyLoad(expr);
- Apply(context_, r0);
}
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitCallWithIC(Call* expr,
@@ -1679,7 +1671,7 @@
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
__ mov(r2, Operand(name));
// Record source position for debugger.
@@ -1687,10 +1679,10 @@
// Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
- __ Call(ic, mode);
+ EmitCallIC(ic, mode);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -1701,9 +1693,9 @@
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
- VisitForValue(key, kAccumulator);
+ VisitForAccumulatorValue(key);
__ mov(r2, r0);
// Record source position for debugger.
SetSourcePosition(expr->position());
@@ -1711,10 +1703,10 @@
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
in_loop);
- __ Call(ic, mode);
+ EmitCallIC(ic, mode);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -1723,7 +1715,7 @@
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
// Record source position for debugger.
SetSourcePosition(expr->position());
@@ -1732,7 +1724,7 @@
__ CallStub(&stub);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- DropAndApply(1, context_, r0);
+ context()->DropAndPlug(1, r0);
}
@@ -1746,7 +1738,7 @@
// resolve the function we need to call and the receiver of the
// call. Then we call the resolved function using the given
// arguments.
- VisitForValue(fun, kStack);
+ VisitForStackValue(fun);
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
__ push(r2); // Reserved receiver slot.
@@ -1754,7 +1746,7 @@
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
@@ -1786,26 +1778,26 @@
__ CallStub(&stub);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- DropAndApply(1, context_, r0);
+ context()->DropAndPlug(1, r0);
} else if (var != NULL && !var->is_this() && var->is_global()) {
// Push global object as receiver for the call IC.
__ ldr(r0, CodeGenerator::GlobalObject());
__ push(r0);
EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
- } else if (var != NULL && var->slot() != NULL &&
- var->slot()->type() == Slot::LOOKUP) {
+ } else if (var != NULL && var->AsSlot() != NULL &&
+ var->AsSlot()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable).
Label slow, done;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLoadFromSlotFastCase(var->slot(),
+ EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
NOT_INSIDE_TYPEOF,
&slow,
&done);
__ bind(&slow);
- // Call the runtime to find the function to call (returned in eax)
+ // Call the runtime to find the function to call (returned in r0)
// and the object holding it (returned in edx).
__ push(context_register());
__ mov(r2, Operand(var->name()));
@@ -1836,21 +1828,21 @@
Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsSymbol()) {
// Call to a named property, use call IC.
- VisitForValue(prop->obj(), kStack);
+ VisitForStackValue(prop->obj());
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
} else {
// Call to a keyed property.
// For a synthetic property use keyed load IC followed by function call,
// for a regular property use keyed CallIC.
- VisitForValue(prop->obj(), kStack);
+ VisitForStackValue(prop->obj());
if (prop->is_synthetic()) {
- VisitForValue(prop->key(), kAccumulator);
+ VisitForAccumulatorValue(prop->key());
// Record source code position for IC call.
SetSourcePosition(prop->position());
__ pop(r1); // We do not need to keep the receiver.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
__ ldr(r1, CodeGenerator::GlobalObject());
__ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
__ Push(r0, r1); // Function, receiver.
@@ -1869,7 +1861,7 @@
loop_depth() == 0) {
lit->set_try_full_codegen(true);
}
- VisitForValue(fun, kStack);
+ VisitForStackValue(fun);
// Load global receiver object.
__ ldr(r1, CodeGenerator::GlobalObject());
__ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
@@ -1889,13 +1881,13 @@
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForValue(expr->expression(), kStack);
+ VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
// Call the construct call builtin that handles allocation and
@@ -1908,59 +1900,59 @@
Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
__ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_true);
__ b(if_false);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ tst(r0, Operand(kSmiTagMask | 0x80000000));
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ LoadRoot(ip, Heap::kNullValueRootIndex);
@@ -1977,41 +1969,41 @@
__ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
Split(le, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
Split(ge, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
@@ -2019,7 +2011,7 @@
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(ne, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
@@ -2028,80 +2020,80 @@
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
// Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
// used in a few functions in runtime.js which should not normally be hit by
// this compiler.
__ jmp(if_false);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE);
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ BranchOnSmi(r0, if_false);
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
@@ -2113,8 +2105,8 @@
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
// Get the frame pointer for the calling frame.
__ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
@@ -2132,7 +2124,7 @@
__ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
@@ -2140,21 +2132,21 @@
ASSERT(args->length() == 2);
// Load the two objects into registers and perform the comparison.
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kAccumulator);
+ VisitForStackValue(args->at(0));
+ VisitForAccumulatorValue(args->at(1));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ pop(r1);
__ cmp(r0, r1);
Split(eq, if_true, if_false, fall_through);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
@@ -2162,13 +2154,13 @@
ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal
- // parameter count in eax.
- VisitForValue(args->at(0), kAccumulator);
+ // parameter count in r0.
+ VisitForAccumulatorValue(args->at(0));
__ mov(r1, r0);
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2190,7 +2182,7 @@
__ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
__ bind(&exit);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2198,7 +2190,7 @@
ASSERT(args->length() == 1);
Label done, null, function, non_function_constructor;
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
// If the object is a smi, we return null.
__ BranchOnSmi(r0, &null);
@@ -2244,7 +2236,7 @@
// All done.
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2259,14 +2251,14 @@
ASSERT_EQ(args->length(), 3);
#ifdef ENABLE_LOGGING_AND_PROFILING
if (CodeGenerator::ShouldGenerateLog(args->at(0))) {
- VisitForValue(args->at(1), kStack);
- VisitForValue(args->at(2), kStack);
+ VisitForStackValue(args->at(1));
+ VisitForStackValue(args->at(2));
__ CallRuntime(Runtime::kLog, 2);
}
#endif
// Finally, we're expected to leave a value on the top of the stack.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2316,7 +2308,7 @@
ExternalReference::fill_heap_number_with_random_function(), 1);
}
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2324,11 +2316,11 @@
// Load the arguments on the stack and call the stub.
SubStringStub stub;
ASSERT(args->length() == 3);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
- VisitForValue(args->at(2), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
+ VisitForStackValue(args->at(2));
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2336,19 +2328,19 @@
// Load the arguments on the stack and call the stub.
RegExpExecStub stub;
ASSERT(args->length() == 4);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
- VisitForValue(args->at(2), kStack);
- VisitForValue(args->at(3), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
+ VisitForStackValue(args->at(2));
+ VisitForStackValue(args->at(3));
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator); // Load the object.
+ VisitForAccumulatorValue(args->at(0)); // Load the object.
Label done;
// If the object is a smi return the object.
@@ -2359,25 +2351,25 @@
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitMathPow(ZoneList<Expression*>* args) {
// Load the arguments on the stack and call the runtime function.
ASSERT(args->length() == 2);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kMath_pow, 2);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitSetValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- VisitForValue(args->at(0), kStack); // Load the object.
- VisitForValue(args->at(1), kAccumulator); // Load the value.
+ VisitForStackValue(args->at(0)); // Load the object.
+ VisitForAccumulatorValue(args->at(1)); // Load the value.
__ pop(r1); // r0 = value. r1 = object.
Label done;
@@ -2395,7 +2387,7 @@
__ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2403,18 +2395,18 @@
ASSERT_EQ(args->length(), 1);
// Load the argument on the stack and call the stub.
- VisitForValue(args->at(0), kStack);
+ VisitForStackValue(args->at(0));
NumberToStringStub stub;
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label done;
StringCharFromCodeGenerator generator(r0, r1);
@@ -2425,15 +2417,15 @@
generator.GenerateSlow(masm_, call_helper);
__ bind(&done);
- Apply(context_, r1);
+ context()->Plug(r1);
}
void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kAccumulator);
+ VisitForStackValue(args->at(0));
+ VisitForAccumulatorValue(args->at(1));
Register object = r1;
Register index = r0;
@@ -2472,15 +2464,15 @@
generator.GenerateSlow(masm_, call_helper);
__ bind(&done);
- Apply(context_, result);
+ context()->Plug(result);
}
void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kAccumulator);
+ VisitForStackValue(args->at(0));
+ VisitForAccumulatorValue(args->at(1));
Register object = r1;
Register index = r0;
@@ -2521,58 +2513,58 @@
generator.GenerateSlow(masm_, call_helper);
__ bind(&done);
- Apply(context_, result);
+ context()->Plug(result);
}
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) {
ASSERT_EQ(2, args->length());
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
StringAddStub stub(NO_STRING_ADD_FLAGS);
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
ASSERT_EQ(2, args->length());
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
StringCompareStub stub;
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the runtime.
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kStack);
+ VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_sin, 1);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the runtime.
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kStack);
+ VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_cos, 1);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitMathSqrt(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the runtime function.
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kStack);
+ VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kMath_sqrt, 1);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2580,38 +2572,38 @@
ASSERT(args->length() >= 2);
int arg_count = args->length() - 2; // For receiver and function.
- VisitForValue(args->at(0), kStack); // Receiver.
+ VisitForStackValue(args->at(0)); // Receiver.
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i + 1), kStack);
+ VisitForStackValue(args->at(i + 1));
}
- VisitForValue(args->at(arg_count + 1), kAccumulator); // Function.
+ VisitForAccumulatorValue(args->at(arg_count + 1)); // Function.
// InvokeFunction requires function in r1. Move it in there.
if (!result_register().is(r1)) __ mov(r1, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(r1, count, CALL_FUNCTION);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitRegExpConstructResult(ZoneList<Expression*>* args) {
ASSERT(args->length() == 3);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
- VisitForValue(args->at(2), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
+ VisitForStackValue(args->at(2));
__ CallRuntime(Runtime::kRegExpConstructResult, 3);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
ASSERT(args->length() == 3);
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kStack);
- VisitForValue(args->at(2), kStack);
+ VisitForStackValue(args->at(0));
+ VisitForStackValue(args->at(1));
+ VisitForStackValue(args->at(2));
__ CallRuntime(Runtime::kSwapElements, 3);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2626,11 +2618,11 @@
if (jsfunction_result_caches->length() <= cache_id) {
__ Abort("Attempt to use undefined cache.");
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- Apply(context_, r0);
+ context()->Plug(r0);
return;
}
- VisitForValue(args->at(1), kAccumulator);
+ VisitForAccumulatorValue(args->at(1));
Register key = r0;
Register cache = r1;
@@ -2662,7 +2654,7 @@
__ CallRuntime(Runtime::kGetFromCache, 2);
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2674,8 +2666,8 @@
Register tmp = r2;
Register tmp2 = r3;
- VisitForValue(args->at(0), kStack);
- VisitForValue(args->at(1), kAccumulator);
+ VisitForStackValue(args->at(0));
+ VisitForAccumulatorValue(args->at(1));
__ pop(left);
Label done, fail, ok;
@@ -2703,19 +2695,19 @@
__ LoadRoot(r0, Heap::kTrueValueRootIndex);
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
}
void FullCodeGenerator::EmitHasCachedArrayIndex(ZoneList<Expression*>* args) {
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
__ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
__ tst(r0, Operand(String::kContainsCachedArrayIndexMask));
@@ -2723,16 +2715,16 @@
__ b(eq, if_true);
__ b(if_false);
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- VisitForValue(args->at(0), kAccumulator);
+ VisitForAccumulatorValue(args->at(0));
__ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
__ IndexFromHash(r0, r0);
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2757,7 +2749,7 @@
// Push the arguments ("left-to-right").
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
- VisitForValue(args->at(i), kStack);
+ VisitForStackValue(args->at(i));
}
if (expr->is_jsruntime()) {
@@ -2765,14 +2757,14 @@
__ mov(r2, Operand(expr->name()));
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
NOT_IN_LOOP);
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
} else {
// Call the C runtime function.
__ CallRuntime(expr->function(), arg_count);
}
- Apply(context_, r0);
+ context()->Plug(r0);
}
@@ -2786,20 +2778,20 @@
// Result of deleting non-property, non-variable reference is true.
// The subexpression may have side effects.
VisitForEffect(expr->expression());
- Apply(context_, true);
+ context()->Plug(true);
} else if (var != NULL &&
!var->is_global() &&
- var->slot() != NULL &&
- var->slot()->type() != Slot::LOOKUP) {
+ var->AsSlot() != NULL &&
+ var->AsSlot()->type() != Slot::LOOKUP) {
// Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects.
- Apply(context_, false);
+ context()->Plug(false);
} else {
// Property or variable reference. Call the delete builtin with
// object and property name as arguments.
if (prop != NULL) {
- VisitForValue(prop->obj(), kStack);
- VisitForValue(prop->key(), kStack);
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
} else if (var->is_global()) {
__ ldr(r1, CodeGenerator::GlobalObject());
__ mov(r0, Operand(var->name()));
@@ -2816,7 +2808,7 @@
__ push(r2);
}
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
- Apply(context_, r0);
+ context()->Plug(r0);
}
break;
}
@@ -2824,26 +2816,7 @@
case Token::VOID: {
Comment cmnt(masm_, "[ UnaryOperation (VOID)");
VisitForEffect(expr->expression());
- switch (context_) {
- case Expression::kUninitialized:
- UNREACHABLE();
- break;
- case Expression::kEffect:
- break;
- case Expression::kValue:
- __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
- switch (location_) {
- case kAccumulator:
- break;
- case kStack:
- __ push(result_register());
- break;
- }
- break;
- case Expression::kTest:
- __ jmp(false_label_);
- break;
- }
+ context()->Plug(Heap::kUndefinedValueRootIndex);
break;
}
@@ -2855,31 +2828,33 @@
Label* fall_through = NULL;
// Notice that the labels are swapped.
- PrepareTest(&materialize_true, &materialize_false,
- &if_false, &if_true, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_false, &if_true, &fall_through);
VisitForControl(expr->expression(), if_true, if_false, fall_through);
- Apply(context_, if_false, if_true); // Labels swapped.
+ context()->Plug(if_false, if_true); // Labels swapped.
break;
}
case Token::TYPEOF: {
Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
- VisitForTypeofValue(expr->expression(), kStack);
+ { StackValueContext context(this);
+ VisitForTypeofValue(expr->expression());
+ }
__ CallRuntime(Runtime::kTypeof, 1);
- Apply(context_, r0);
+ context()->Plug(r0);
break;
}
case Token::ADD: {
Comment cmt(masm_, "[ UnaryOperation (ADD)");
- VisitForValue(expr->expression(), kAccumulator);
+ VisitForAccumulatorValue(expr->expression());
Label no_conversion;
__ tst(result_register(), Operand(kSmiTagMask));
__ b(eq, &no_conversion);
__ push(r0);
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
__ bind(&no_conversion);
- Apply(context_, result_register());
+ context()->Plug(result_register());
break;
}
@@ -2888,12 +2863,14 @@
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
- GenericUnaryOpStub stub(Token::SUB, overwrite);
+ GenericUnaryOpStub stub(Token::SUB,
+ overwrite,
+ NO_UNARY_FLAGS);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register r0.
- VisitForValue(expr->expression(), kAccumulator);
+ VisitForAccumulatorValue(expr->expression());
__ CallStub(&stub);
- Apply(context_, r0);
+ context()->Plug(r0);
break;
}
@@ -2901,9 +2878,10 @@
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
// The generic unary operation stub expects the argument to be
// in the accumulator register r0.
- VisitForValue(expr->expression(), kAccumulator);
+ VisitForAccumulatorValue(expr->expression());
Label done;
- if (ShouldInlineSmiCase(expr->op())) {
+ bool inline_smi_code = ShouldInlineSmiCase(expr->op());
+ if (inline_smi_code) {
Label call_stub;
__ BranchOnNotSmi(r0, &call_stub);
__ mvn(r0, Operand(r0));
@@ -2913,12 +2891,15 @@
__ bind(&call_stub);
}
bool overwrite = expr->expression()->ResultOverwriteAllowed();
+ UnaryOpFlags flags = inline_smi_code
+ ? NO_UNARY_SMI_CODE_IN_STUB
+ : NO_UNARY_FLAGS;
UnaryOverwriteMode mode =
overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
- GenericUnaryOpStub stub(Token::BIT_NOT, mode);
+ GenericUnaryOpStub stub(Token::BIT_NOT, mode, flags);
__ CallStub(&stub);
__ bind(&done);
- Apply(context_, r0);
+ context()->Plug(r0);
break;
}
@@ -2954,25 +2935,22 @@
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
- Location saved_location = location_;
- location_ = kAccumulator;
- EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
- Expression::kValue);
- location_ = saved_location;
+ AccumulatorValueContext context(this);
+ EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
} else {
// Reserve space for result of postfix operation.
- if (expr->is_postfix() && context_ != Expression::kEffect) {
+ if (expr->is_postfix() && !context()->IsEffect()) {
__ mov(ip, Operand(Smi::FromInt(0)));
__ push(ip);
}
if (assign_type == NAMED_PROPERTY) {
// Put the object both on the stack and in the accumulator.
- VisitForValue(prop->obj(), kAccumulator);
+ VisitForAccumulatorValue(prop->obj());
__ push(r0);
EmitNamedPropertyLoad(prop);
} else {
- VisitForValue(prop->obj(), kStack);
- VisitForValue(prop->key(), kAccumulator);
+ VisitForStackValue(prop->obj());
+ VisitForAccumulatorValue(prop->key());
__ ldr(r1, MemOperand(sp, 0));
__ push(r0);
EmitKeyedPropertyLoad(prop);
@@ -2988,29 +2966,21 @@
// Save result for postfix expressions.
if (expr->is_postfix()) {
- switch (context_) {
- case Expression::kUninitialized:
- UNREACHABLE();
- case Expression::kEffect:
- // Do not save result.
- break;
- case Expression::kValue:
- case Expression::kTest:
- // Save the result on the stack. If we have a named or keyed property
- // we store the result under the receiver that is currently on top
- // of the stack.
- switch (assign_type) {
- case VARIABLE:
- __ push(r0);
- break;
- case NAMED_PROPERTY:
- __ str(r0, MemOperand(sp, kPointerSize));
- break;
- case KEYED_PROPERTY:
- __ str(r0, MemOperand(sp, 2 * kPointerSize));
- break;
- }
- break;
+ if (!context()->IsEffect()) {
+ // Save the result on the stack. If we have a named or keyed property
+ // we store the result under the receiver that is currently on top
+ // of the stack.
+ switch (assign_type) {
+ case VARIABLE:
+ __ push(r0);
+ break;
+ case NAMED_PROPERTY:
+ __ str(r0, MemOperand(sp, kPointerSize));
+ break;
+ case KEYED_PROPERTY:
+ __ str(r0, MemOperand(sp, 2 * kPointerSize));
+ break;
+ }
}
}
@@ -3037,31 +3007,31 @@
switch (assign_type) {
case VARIABLE:
if (expr->is_postfix()) {
- EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN,
- Expression::kEffect);
- // For all contexts except kEffect: We have the result on
+ { EffectContext context(this);
+ EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
+ Token::ASSIGN);
+ }
+ // For all contexts except EffectConstant We have the result on
// top of the stack.
- if (context_ != Expression::kEffect) {
- ApplyTOS(context_);
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
}
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
- Token::ASSIGN,
- context_);
+ Token::ASSIGN);
}
break;
case NAMED_PROPERTY: {
__ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
__ pop(r1);
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
if (expr->is_postfix()) {
- if (context_ != Expression::kEffect) {
- ApplyTOS(context_);
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
}
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
break;
}
@@ -3069,13 +3039,13 @@
__ pop(r1); // Key.
__ pop(r2); // Receiver.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- __ Call(ic, RelocInfo::CODE_TARGET);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
if (expr->is_postfix()) {
- if (context_ != Expression::kEffect) {
- ApplyTOS(context_);
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
}
} else {
- Apply(context_, r0);
+ context()->Plug(r0);
}
break;
}
@@ -3083,7 +3053,9 @@
}
-void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) {
+void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
+ ASSERT(!context()->IsEffect());
+ ASSERT(!context()->IsTest());
VariableProxy* proxy = expr->AsVariableProxy();
if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable");
@@ -3092,16 +3064,16 @@
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// Use a regular load, not a contextual load, to avoid a reference
// error.
- __ Call(ic, RelocInfo::CODE_TARGET);
- if (where == kStack) __ push(r0);
+ EmitCallIC(ic, RelocInfo::CODE_TARGET);
+ context()->Plug(r0);
} else if (proxy != NULL &&
- proxy->var()->slot() != NULL &&
- proxy->var()->slot()->type() == Slot::LOOKUP) {
+ proxy->var()->AsSlot() != NULL &&
+ proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- Slot* slot = proxy->var()->slot();
+ Slot* slot = proxy->var()->AsSlot();
EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
@@ -3110,10 +3082,10 @@
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
__ bind(&done);
- if (where == kStack) __ push(r0);
+ context()->Plug(r0);
} else {
// This expression cannot throw a reference error at the top level.
- VisitForValue(expr, where);
+ Visit(expr);
}
}
@@ -3135,7 +3107,9 @@
if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
Handle<String> check = Handle<String>::cast(right_literal_value);
- VisitForTypeofValue(left_unary->expression(), kAccumulator);
+ { AccumulatorValueContext context(this);
+ VisitForTypeofValue(left_unary->expression());
+ }
if (check->Equals(Heap::number_symbol())) {
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, if_true);
@@ -3221,8 +3195,8 @@
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
// First we try a fast inlined version of the compare when one of
// the operands is a literal.
@@ -3230,14 +3204,14 @@
Expression* left = expr->left();
Expression* right = expr->right();
if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
return;
}
- VisitForValue(expr->left(), kStack);
+ VisitForStackValue(expr->left());
switch (op) {
case Token::IN:
- VisitForValue(expr->right(), kStack);
+ VisitForStackValue(expr->right());
__ InvokeBuiltin(Builtins::IN, CALL_JS);
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r0, ip);
@@ -3245,7 +3219,7 @@
break;
case Token::INSTANCEOF: {
- VisitForValue(expr->right(), kStack);
+ VisitForStackValue(expr->right());
InstanceofStub stub;
__ CallStub(&stub);
// The stub returns 0 for true.
@@ -3255,7 +3229,7 @@
}
default: {
- VisitForValue(expr->right(), kAccumulator);
+ VisitForAccumulatorValue(expr->right());
Condition cc = eq;
bool strict = false;
switch (op) {
@@ -3292,7 +3266,8 @@
UNREACHABLE();
}
- if (ShouldInlineSmiCase(op)) {
+ bool inline_smi_code = ShouldInlineSmiCase(op);
+ if (inline_smi_code) {
Label slow_case;
__ orr(r2, r0, Operand(r1));
__ BranchOnNotSmi(r2, &slow_case);
@@ -3300,8 +3275,10 @@
Split(cc, if_true, if_false, NULL);
__ bind(&slow_case);
}
-
- CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
+ CompareFlags flags = inline_smi_code
+ ? NO_SMI_COMPARE_IN_STUB
+ : NO_COMPARE_FLAGS;
+ CompareStub stub(cc, strict, flags, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0, RelocInfo::NONE));
Split(cc, if_true, if_false, fall_through);
@@ -3310,7 +3287,7 @@
// Convert the result of the comparison into one expected for this
// expression's context.
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
@@ -3320,10 +3297,10 @@
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
- PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
+ context()->PrepareTest(&materialize_true, &materialize_false,
+ &if_true, &if_false, &fall_through);
- VisitForValue(expr->expression(), kAccumulator);
+ VisitForAccumulatorValue(expr->expression());
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ cmp(r0, r1);
if (expr->is_strict()) {
@@ -3342,20 +3319,31 @@
__ cmp(r1, Operand(1 << Map::kIsUndetectable));
Split(eq, if_true, if_false, fall_through);
}
- Apply(context_, if_true, if_false);
+ context()->Plug(if_true, if_false);
}
void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- Apply(context_, r0);
+ context()->Plug(r0);
}
-Register FullCodeGenerator::result_register() { return r0; }
+Register FullCodeGenerator::result_register() {
+ return r0;
+}
-Register FullCodeGenerator::context_register() { return cp; }
+Register FullCodeGenerator::context_register() {
+ return cp;
+}
+
+
+void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
+ ASSERT(mode == RelocInfo::CODE_TARGET ||
+ mode == RelocInfo::CODE_TARGET_CONTEXT);
+ __ Call(ic, mode);
+}
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 1a76db2..d5a700c 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -967,6 +967,14 @@
}
+bool LoadIC::PatchInlinedContextualLoad(Address address,
+ Object* map,
+ Object* cell) {
+ // TODO(<bug#>): implement this.
+ return false;
+}
+
+
bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
// Find the end of the inlined code for the store if there is an
// inlined version of the store.
@@ -1236,7 +1244,6 @@
// -- r1 : receiver
// -----------------------------------
Label miss;
- Label index_out_of_range;
Register receiver = r1;
Register index = r0;
@@ -1251,7 +1258,7 @@
result,
&miss, // When not a string.
&miss, // When not a number.
- &index_out_of_range,
+ &miss, // When index out of range.
STRING_INDEX_IS_ARRAY_INDEX);
char_at_generator.GenerateFast(masm);
__ Ret();
@@ -1259,10 +1266,6 @@
ICRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, call_helper);
- __ bind(&index_out_of_range);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- __ Ret();
-
__ bind(&miss);
GenerateMiss(masm);
}
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 3554431..0e2c49e 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1242,15 +1242,6 @@
}
-void MacroAssembler::StubReturn(int argc, Condition cond) {
- ASSERT(argc >= 1 && generating_stub());
- if (argc > 1) {
- add(sp, sp, Operand((argc - 1) * kPointerSize), LeaveCC, cond);
- }
- Ret(cond);
-}
-
-
void MacroAssembler::IllegalOperation(int num_arguments) {
if (num_arguments > 0) {
add(sp, sp, Operand(num_arguments * kPointerSize));
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index febd87e..48a8059 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -531,9 +531,6 @@
// Call a code stub.
void TailCallStub(CodeStub* stub, Condition cond = al);
- // Return from a code stub after popping its arguments.
- void StubReturn(int argc, Condition cond = al);
-
// Call a runtime routine.
void CallRuntime(Runtime::Function* f, int num_arguments);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 0da5f64..659f29c 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -266,7 +266,12 @@
void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
- MacroAssembler* masm, int index, Register prototype) {
+ MacroAssembler* masm, int index, Register prototype, Label* miss) {
+ // Check we're still in the same context.
+ __ ldr(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ Move(ip, Top::global());
+ __ cmp(prototype, ip);
+ __ b(ne, miss);
// Get the global function with the given index.
JSFunction* function = JSFunction::cast(Top::global_context()->get(index));
// Load its initial map. The global functions all have initial maps.
@@ -1434,7 +1439,8 @@
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
- r0);
+ r0,
+ &miss);
ASSERT(object != holder);
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder,
r1, r3, r4, name, &miss);
@@ -1505,7 +1511,8 @@
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX,
- r0);
+ r0,
+ &miss);
ASSERT(object != holder);
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder,
r1, r3, r4, name, &miss);
@@ -1626,6 +1633,16 @@
}
+Object* CallStubCompiler::CompileMathFloorCall(Object* object,
+ JSObject* holder,
+ JSGlobalPropertyCell* cell,
+ JSFunction* function,
+ String* name) {
+ // TODO(872): implement this.
+ return Heap::undefined_value();
+}
+
+
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
@@ -1705,7 +1722,7 @@
__ b(hs, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::STRING_FUNCTION_INDEX, r0);
+ masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
r1, r4, name, &miss);
}
@@ -1725,7 +1742,7 @@
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::NUMBER_FUNCTION_INDEX, r0);
+ masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
r1, r4, name, &miss);
}
@@ -1748,7 +1765,7 @@
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::BOOLEAN_FUNCTION_INDEX, r0);
+ masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
r1, r4, name, &miss);
}
@@ -2067,7 +2084,10 @@
name,
r1,
&miss);
- if (cell->IsFailure()) return cell;
+ if (cell->IsFailure()) {
+ miss.Unuse();
+ return cell;
+ }
}
// Return undefined if maps of the full prototype chain are still the
@@ -2117,7 +2137,10 @@
Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4,
callback, name, &miss, &failure);
- if (!success) return failure;
+ if (!success) {
+ miss.Unuse();
+ return failure;
+ }
__ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -2212,11 +2235,11 @@
}
__ mov(r0, r4);
- __ IncrementCounter(&Counters::named_load_global_inline, 1, r1, r3);
+ __ IncrementCounter(&Counters::named_load_global_stub, 1, r1, r3);
__ Ret();
__ bind(&miss);
- __ IncrementCounter(&Counters::named_load_global_inline_miss, 1, r1, r3);
+ __ IncrementCounter(&Counters::named_load_global_stub_miss, 1, r1, r3);
GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
@@ -2265,7 +2288,10 @@
Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4,
callback, name, &miss, &failure);
- if (!success) return failure;
+ if (!success) {
+ miss.Unuse();
+ return failure;
+ }
__ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);