frame_->CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
}
frame_->EmitPush(r0); // save the result
- // r0: created object literal
-
for (int i = 0; i < node->properties()->length(); i++) {
+ // At the start of each iteration, the top of stack contains
+ // the newly created object literal.
ObjectLiteral::Property* property = node->properties()->at(i);
Literal* key = property->key();
Expression* value = property->value();
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
// else fall through
- case ObjectLiteral::Property::COMPUTED: // fall through
+ case ObjectLiteral::Property::COMPUTED:
+ if (key->handle()->IsSymbol()) {
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ LoadAndSpill(value);
+ frame_->EmitPop(r0);
+ __ mov(r2, Operand(key->handle()));
+ __ ldr(r1, frame_->Top()); // Load the receiver.
+ frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+ break;
+ }
+ // else fall through
case ObjectLiteral::Property::PROTOTYPE: {
+ __ ldr(r0, frame_->Top());
frame_->EmitPush(r0); // dup the result
LoadAndSpill(key);
LoadAndSpill(value);
frame_->CallRuntime(Runtime::kSetProperty, 3);
- // restore r0
- __ ldr(r0, frame_->Top());
break;
}
case ObjectLiteral::Property::SETTER: {
+ __ ldr(r0, frame_->Top());
frame_->EmitPush(r0);
LoadAndSpill(key);
__ mov(r0, Operand(Smi::FromInt(1)));
frame_->EmitPush(r0);
LoadAndSpill(value);
frame_->CallRuntime(Runtime::kDefineAccessor, 4);
- __ ldr(r0, frame_->Top());
break;
}
case ObjectLiteral::Property::GETTER: {
+ __ ldr(r0, frame_->Top());
frame_->EmitPush(r0);
LoadAndSpill(key);
__ mov(r0, Operand(Smi::FromInt(0)));
frame_->EmitPush(r0);
LoadAndSpill(value);
frame_->CallRuntime(Runtime::kDefineAccessor, 4);
- __ ldr(r0, frame_->Top());
break;
}
}
Handle<String> name(GetName());
frame->EmitPop(r0);
- // Setup the name register.
+ frame->EmitPop(r1);
__ mov(r2, Operand(name));
frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
frame->EmitPush(r0);
- cgen_->UnloadReference(this);
+ set_unloaded();
break;
}
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
- // Registers r0 and r2 contain objects that needs to be pushed on the
+ // Registers r0 and r2 contain objects that need to be pushed on the
// expression stack of the fake JS frame.
Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
}
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC store (from ic-arm.cc).
// ----------- S t a t e -------------
- // -- r0 : receiver
+ // -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
- // Registers r0 and r2 contain objects that needs to be pushed on the
+ // Registers r0, r1, and r2 contain objects that need to be pushed on the
// expression stack of the fake JS frame.
- Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());
+ Generate_DebugBreakCallHelper(masm, r0.bit() | r1.bit() | r2.bit());
}
if (key->handle()->IsSymbol()) {
VisitForValue(value, kAccumulator);
__ mov(r2, Operand(key->handle()));
+ __ ldr(r1, MemOperand(sp));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
- // StoreIC leaves the receiver on the stack.
break;
}
// Fall through.
ASSERT(!var->is_this());
// Assignment to a global variable. Use inline caching for the
// assignment. Right-hand-side value is passed in r0, variable name in
- // r2, and the global object on the stack.
+ // r2, and the global object in r1.
__ mov(r2, Operand(var->name()));
- __ ldr(ip, CodeGenerator::GlobalObject());
- __ push(ip);
+ __ ldr(r1, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
- // Overwrite the global object on the stack with the result if needed.
- DropAndApply(1, context, r0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
__ push(result_register()); // Value.
__ mov(r1, Operand(var->name()));
__ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name.
__ CallRuntime(Runtime::kStoreContextSlot, 3);
- Apply(context, r0);
} else if (var->slot() != NULL) {
Slot* slot = var->slot();
UNREACHABLE();
break;
}
- Apply(context, result_register());
} else {
// Variables rewritten as properties are not treated as variables in
// assignments.
UNREACHABLE();
}
+ Apply(context, result_register());
}
// Record source code position before IC call.
SetSourcePosition(expr->position());
__ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
+ if (expr->ends_initialization_block()) {
+ __ ldr(r1, MemOperand(sp));
+ } else {
+ __ pop(r1);
+ }
+
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
__ push(ip);
__ CallRuntime(Runtime::kToFastProperties, 1);
__ pop(r0);
+ DropAndApply(1, context_, r0);
+ } else {
+ Apply(context_, r0);
}
-
- DropAndApply(1, context_, r0);
}
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);
if (expr->is_postfix()) {
- __ Drop(1); // Result is on the stack under the receiver.
if (context_ != Expression::kEffect) {
ApplyTOS(context_);
}
} else {
- DropAndApply(1, context_, r0);
+ Apply(context_, r0);
}
break;
}
void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
// Get the receiver from the stack and probe the stub cache.
- __ ldr(r1, MemOperand(sp));
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
NOT_IN_LOOP,
MONOMORPHIC);
void StoreIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
- __ ldr(r3, MemOperand(sp)); // copy receiver
- __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+ __ push(r1);
+ __ stm(db_w, sp, r2.bit() | r0.bit());
// Perform tail call to the entry.
__ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1);
// Generate StoreField code, value is passed in r0 register.
-// After executing generated code, the receiver_reg and name_reg
-// may be clobbered.
+// When leaving generated code after success, the receiver_reg and name_reg
+// may be clobbered. Upon branch to miss_label, the receiver and name
+// registers have their original values.
void StubCompiler::GenerateStoreField(MacroAssembler* masm,
JSObject* object,
int index,
// Note: starting a frame here makes GC aware of pointers pushed below.
__ EnterInternalFrame();
- if (lookup->type() == CALLBACKS) {
- __ push(receiver);
- }
+ __ push(receiver);
__ push(holder);
__ push(name_);
__ bind(&interceptor_failed);
__ pop(name_);
__ pop(holder);
-
- if (lookup->type() == CALLBACKS) {
- __ pop(receiver);
- }
+ __ pop(receiver);
__ LeaveInternalFrame();
String* name) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- // Get the receiver from the stack.
- __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
- // name register might be clobbered.
GenerateStoreField(masm(),
object,
index,
transition,
- r3, r2, r1,
+ r1, r2, r3,
&miss);
__ bind(&miss);
- __ mov(r2, Operand(Handle<String>(name))); // restore name
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
__ Jump(ic, RelocInfo::CODE_TARGET);
String* name) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- // Get the object from the stack.
- __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
// Check that the object isn't a smi.
- __ tst(r3, Operand(kSmiTagMask));
+ __ tst(r1, Operand(kSmiTagMask));
__ b(eq, &miss);
// Check that the map of the object hasn't changed.
- __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ cmp(r1, Operand(Handle<Map>(object->map())));
+ __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ cmp(r3, Operand(Handle<Map>(object->map())));
__ b(ne, &miss);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(r3, r1, &miss);
+ __ CheckAccessGlobalProxy(r1, r3, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- __ ldr(ip, MemOperand(sp)); // receiver
- __ push(ip);
+ __ push(r1); // receiver
__ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback info
- __ push(ip);
- __ push(r2); // name
- __ push(r0); // value
+ __ stm(db_w, sp, ip.bit() | r2.bit() | r0.bit());
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
String* name) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
- // Get the object from the stack.
- __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
-
// Check that the object isn't a smi.
- __ tst(r3, Operand(kSmiTagMask));
+ __ tst(r1, Operand(kSmiTagMask));
__ b(eq, &miss);
// Check that the map of the object hasn't changed.
- __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ cmp(r1, Operand(Handle<Map>(receiver->map())));
+ __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ cmp(r3, Operand(Handle<Map>(receiver->map())));
__ b(ne, &miss);
// Perform global security token check if needed.
if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(r3, r1, &miss);
+ __ CheckAccessGlobalProxy(r1, r3, &miss);
}
- // Stub never generated for non-global objects that require access
+ // Stub is never generated for non-global objects that require access
// checks.
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
- __ ldr(ip, MemOperand(sp)); // receiver
- __ push(ip);
- __ push(r2); // name
- __ push(r0); // value
+ __ push(r1); // receiver.
+ __ push(r2); // name.
+ __ push(r0); // value.
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
String* name) {
// ----------- S t a t e -------------
// -- r0 : value
+ // -- r1 : receiver
// -- r2 : name
// -- lr : return address
- // -- [sp] : receiver
// -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
__ cmp(r3, Operand(Handle<Map>(object->map())));
__ b(ne, &miss);
__ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell)));
__ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
- __ IncrementCounter(&Counters::named_store_global_inline, 1, r1, r3);
+ __ IncrementCounter(&Counters::named_store_global_inline, 1, r4, r3);
__ Ret();
// Handle store cache miss.
__ bind(&miss);
- __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r1, r3);
+ __ IncrementCounter(&Counters::named_store_global_inline_miss, 1, r4, r3);
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
__ Jump(ic, RelocInfo::CODE_TARGET);