Change StoreIC interface on ARM platform
Review URL: http://codereview.chromium.org/554152 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3830 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5ecfd4bfe9
commit
9344612bef
@ -2718,9 +2718,9 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
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();
|
||||
@ -2730,34 +2730,43 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -4388,11 +4397,11 @@ void Reference::SetValue(InitState init_state) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// -- 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());
|
||||
}
|
||||
@ -137,14 +137,14 @@ void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -816,9 +816,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
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.
|
||||
@ -945,21 +945,17 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
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();
|
||||
@ -986,13 +982,13 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
Apply(context, result_register());
|
||||
|
||||
} else {
|
||||
// Variables rewritten as properties are not treated as variables in
|
||||
// assignments.
|
||||
UNREACHABLE();
|
||||
}
|
||||
Apply(context, result_register());
|
||||
}
|
||||
|
||||
|
||||
@ -1016,6 +1012,12 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// 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);
|
||||
|
||||
@ -1026,9 +1028,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
__ push(ip);
|
||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||
__ pop(r0);
|
||||
DropAndApply(1, context_, r0);
|
||||
} else {
|
||||
Apply(context_, r0);
|
||||
}
|
||||
|
||||
DropAndApply(1, context_, r0);
|
||||
}
|
||||
|
||||
|
||||
@ -1548,15 +1551,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
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;
|
||||
}
|
||||
|
@ -791,13 +791,12 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
|
||||
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);
|
||||
@ -811,13 +810,13 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
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);
|
||||
|
@ -258,8 +258,9 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
|
||||
|
||||
|
||||
// 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,
|
||||
@ -525,9 +526,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
// 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_);
|
||||
|
||||
@ -548,10 +547,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
|
||||
__ bind(&interceptor_failed);
|
||||
__ pop(name_);
|
||||
__ pop(holder);
|
||||
|
||||
if (lookup->type() == CALLBACKS) {
|
||||
__ pop(receiver);
|
||||
}
|
||||
__ pop(receiver);
|
||||
|
||||
__ LeaveInternalFrame();
|
||||
|
||||
@ -1208,24 +1204,19 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
|
||||
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);
|
||||
|
||||
@ -1239,39 +1230,33 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
|
||||
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 =
|
||||
@ -1292,37 +1277,33 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
|
||||
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 =
|
||||
@ -1344,14 +1325,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
|
||||
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);
|
||||
@ -1360,12 +1340,12 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
|
||||
__ 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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user