Commit 019b8c45 authored by whesse@chromium.org's avatar whesse@chromium.org

Change the interface of LoadIC on the x64 platform to take its arguments in registers.

Review URL: http://codereview.chromium.org/2330003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4759 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 29cee68e
...@@ -56,15 +56,14 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, ...@@ -56,15 +56,14 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
// //
// t0 - used to hold the property dictionary. // t0 - used to hold the property dictionary.
// //
// t1 - initially the receiver // t1 - initially the receiver.
// - used for the index into the property dictionary
// - holds the result on exit. // - holds the result on exit.
// //
// r3 - used as temporary and to hold the capacity of the property // r3 - used as temporary and to hold the capacity of the property
// dictionary. // dictionary.
// //
// r2 - holds the name of the property and is unchanged. // r2 - initially holds the name of the property and is unchanged.
// r4 - used as temporary. // r4 - used to hold the index into the property dictionary.
Label done; Label done;
...@@ -542,7 +541,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -542,7 +541,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
__ CheckAccessGlobalProxy(r0, r1, &miss); __ CheckAccessGlobalProxy(r0, r1, &miss);
__ b(&probe); __ b(&probe);
// Cache miss: Restore receiver from stack and jump to runtime. // Cache miss: Jump to runtime.
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
} }
......
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
...@@ -1322,7 +1322,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -1322,7 +1322,7 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
__ CheckAccessGlobalProxy(eax, edx, &miss); __ CheckAccessGlobalProxy(eax, edx, &miss);
__ jmp(&probe); __ jmp(&probe);
// Cache miss: Restore receiver from stack and jump to runtime. // Cache miss: Jump to runtime.
__ bind(&miss); __ bind(&miss);
GenerateMiss(masm); GenerateMiss(masm);
} }
......
...@@ -794,6 +794,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand, ...@@ -794,6 +794,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
// Load applicand.apply onto the stack. This will usually // Load applicand.apply onto the stack. This will usually
// give us a megamorphic load site. Not super, but it works. // give us a megamorphic load site. Not super, but it works.
Load(applicand); Load(applicand);
frame()->Dup();
Handle<String> name = Factory::LookupAsciiSymbol("apply"); Handle<String> name = Factory::LookupAsciiSymbol("apply");
frame()->Push(name); frame()->Push(name);
Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
...@@ -5791,8 +5792,6 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( ...@@ -5791,8 +5792,6 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// property case was inlined. Ensure that there is not a test rax // property case was inlined. Ensure that there is not a test rax
// instruction here. // instruction here.
masm_->nop(); masm_->nop();
// Discard the global object. The result is in answer.
frame_->Drop();
return answer; return answer;
} }
...@@ -6740,7 +6739,9 @@ class DeferredReferenceGetNamedValue: public DeferredCode { ...@@ -6740,7 +6739,9 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
void DeferredReferenceGetNamedValue::Generate() { void DeferredReferenceGetNamedValue::Generate() {
__ push(receiver_); if (!receiver_.is(rax)) {
__ movq(rax, receiver_);
}
__ Move(rcx, name_); __ Move(rcx, name_);
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
...@@ -6757,7 +6758,6 @@ void DeferredReferenceGetNamedValue::Generate() { ...@@ -6757,7 +6758,6 @@ void DeferredReferenceGetNamedValue::Generate() {
__ IncrementCounter(&Counters::named_load_inline_miss, 1); __ IncrementCounter(&Counters::named_load_inline_miss, 1);
if (!dst_.is(rax)) __ movq(dst_, rax); if (!dst_.is(rax)) __ movq(dst_, rax);
__ pop(receiver_);
} }
...@@ -7418,9 +7418,8 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { ...@@ -7418,9 +7418,8 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
__ IncrementCounter(&Counters::named_load_inline, 1); __ IncrementCounter(&Counters::named_load_inline, 1);
deferred->BindExit(); deferred->BindExit();
frame()->Push(&receiver);
} }
ASSERT(frame()->height() == original_height); ASSERT(frame()->height() == original_height - 1);
return result; return result;
} }
...@@ -7569,10 +7568,13 @@ void Reference::GetValue() { ...@@ -7569,10 +7568,13 @@ void Reference::GetValue() {
Variable* var = expression_->AsVariableProxy()->AsVariable(); Variable* var = expression_->AsVariableProxy()->AsVariable();
bool is_global = var != NULL; bool is_global = var != NULL;
ASSERT(!is_global || var->is_global()); ASSERT(!is_global || var->is_global());
if (persist_after_get_) {
cgen_->frame()->Dup();
}
Result result = cgen_->EmitNamedLoad(GetName(), is_global); Result result = cgen_->EmitNamedLoad(GetName(), is_global);
cgen_->frame()->Push(&result); cgen_->frame()->Push(&result);
if (!persist_after_get_) { if (!persist_after_get_) {
cgen_->UnloadReference(this); set_unloaded();
} }
break; break;
} }
......
...@@ -144,9 +144,10 @@ void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { ...@@ -144,9 +144,10 @@ void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-x64.cc). // Register state for IC load call (from ic-x64.cc).
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// ----------------------------------- // -----------------------------------
Generate_DebugBreakCallHelper(masm, rcx.bit(), false); Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false);
} }
......
...@@ -1127,15 +1127,15 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var, ...@@ -1127,15 +1127,15 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var,
Comment cmnt(masm_, "Global variable"); Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in rcx and the global // Use inline caching. Variable name is passed in rcx and the global
// object on the stack. // object on the stack.
__ push(CodeGenerator::GlobalObject());
__ Move(rcx, var->name()); __ Move(rcx, var->name());
__ movq(rax, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
// A test rax instruction following the call is used by the IC to // A test rax instruction following the call is used by the IC to
// indicate that the inobject property case was inlined. Ensure there // indicate that the inobject property case was inlined. Ensure there
// is no test rax instruction here. // is no test rax instruction here.
__ nop(); __ nop();
DropAndApply(1, context, rax); Apply(context, rax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) { } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
Comment cmnt(masm_, "Lookup slot"); Comment cmnt(masm_, "Lookup slot");
...@@ -1693,14 +1693,12 @@ void FullCodeGenerator::VisitProperty(Property* expr) { ...@@ -1693,14 +1693,12 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property"); Comment cmnt(masm_, "[ Property");
Expression* key = expr->key(); Expression* key = expr->key();
// Evaluate receiver.
VisitForValue(expr->obj(), kStack);
if (key->IsPropertyName()) { if (key->IsPropertyName()) {
VisitForValue(expr->obj(), kAccumulator);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
// Drop receiver left on the stack by IC. Apply(context_, rax);
DropAndApply(1, context_, rax);
} else { } else {
VisitForValue(expr->obj(), kStack);
VisitForValue(expr->key(), kStack); VisitForValue(expr->key(), kStack);
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
// Drop key and receiver left on the stack by IC. // Drop key and receiver left on the stack by IC.
...@@ -2745,13 +2743,13 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ...@@ -2745,13 +2743,13 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
!proxy->var()->is_this() && !proxy->var()->is_this() &&
proxy->var()->is_global()) { proxy->var()->is_global()) {
Comment cmnt(masm_, "Global variable"); Comment cmnt(masm_, "Global variable");
__ push(CodeGenerator::GlobalObject());
__ Move(rcx, proxy->name()); __ Move(rcx, proxy->name());
__ movq(rax, CodeGenerator::GlobalObject());
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
// Use a regular load, not a contextual load, to avoid a reference // Use a regular load, not a contextual load, to avoid a reference
// error. // error.
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
__ movq(Operand(rsp, 0), rax); __ push(rax);
} else if (proxy != NULL && } else if (proxy != NULL &&
proxy->var()->slot() != NULL && proxy->var()->slot() != NULL &&
proxy->var()->slot()->type() == Slot::LOOKUP) { proxy->var()->slot()->type() == Slot::LOOKUP) {
...@@ -2861,10 +2859,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -2861,10 +2859,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && context_ != Expression::kEffect) { if (expr->is_postfix() && context_ != Expression::kEffect) {
__ Push(Smi::FromInt(0)); __ Push(Smi::FromInt(0));
} }
VisitForValue(prop->obj(), kStack);
if (assign_type == NAMED_PROPERTY) { if (assign_type == NAMED_PROPERTY) {
VisitForValue(prop->obj(), kAccumulator);
__ push(rax); // Copy of receiver, needed for later store.
EmitNamedPropertyLoad(prop); EmitNamedPropertyLoad(prop);
} else { } else {
VisitForValue(prop->obj(), kStack);
VisitForValue(prop->key(), kStack); VisitForValue(prop->key(), kStack);
EmitKeyedPropertyLoad(prop); EmitKeyedPropertyLoad(prop);
} }
......
...@@ -56,18 +56,20 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, ...@@ -56,18 +56,20 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
Register r1, Register r1,
Register r2, Register r2,
Register name, Register name,
Register r4,
DictionaryCheck check_dictionary) { DictionaryCheck check_dictionary) {
// Register use: // Register use:
// //
// r0 - used to hold the property dictionary. // r0 - used to hold the property dictionary.
// //
// r1 - initially the receiver // r1 - initially the receiver.
// - used for the index into the property dictionary // - unchanged on any jump to miss_label.
// - holds the result on exit. // - holds the result on exit.
// //
// r2 - used to hold the capacity of the property dictionary. // r2 - used to hold the capacity of the property dictionary.
// //
// name - holds the name of the property and is unchanged. // name - holds the name of the property and is unchanged.
// r4 - used to hold the index into the property dictionary.
Label done; Label done;
...@@ -116,19 +118,19 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, ...@@ -116,19 +118,19 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
StringDictionary::kElementsStartIndex * kPointerSize; StringDictionary::kElementsStartIndex * kPointerSize;
for (int i = 0; i < kProbes; i++) { for (int i = 0; i < kProbes; i++) {
// Compute the masked index: (hash + i + i * i) & mask. // Compute the masked index: (hash + i + i * i) & mask.
__ movl(r1, FieldOperand(name, String::kHashFieldOffset)); __ movl(r4, FieldOperand(name, String::kHashFieldOffset));
__ shrl(r1, Immediate(String::kHashShift)); __ shrl(r4, Immediate(String::kHashShift));
if (i > 0) { if (i > 0) {
__ addl(r1, Immediate(StringDictionary::GetProbeOffset(i))); __ addl(r4, Immediate(StringDictionary::GetProbeOffset(i)));
} }
__ and_(r1, r2); __ and_(r4, r2);
// Scale the index by multiplying by the entry size. // Scale the index by multiplying by the entry size.
ASSERT(StringDictionary::kEntrySize == 3); ASSERT(StringDictionary::kEntrySize == 3);
__ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 __ lea(r4, Operand(r4, r4, times_2, 0)); // r4 = r4 * 3
// Check if the key is identical to the name. // Check if the key is identical to the name.
__ cmpq(name, Operand(r0, r1, times_pointer_size, __ cmpq(name, Operand(r0, r4, times_pointer_size,
kElementsStartOffset - kHeapObjectTag)); kElementsStartOffset - kHeapObjectTag));
if (i != kProbes - 1) { if (i != kProbes - 1) {
__ j(equal, &done); __ j(equal, &done);
...@@ -140,14 +142,14 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, ...@@ -140,14 +142,14 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
// Check that the value is a normal property. // Check that the value is a normal property.
__ bind(&done); __ bind(&done);
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ Test(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), __ Test(Operand(r0, r4, times_pointer_size, kDetailsOffset - kHeapObjectTag),
Smi::FromInt(PropertyDetails::TypeField::mask())); Smi::FromInt(PropertyDetails::TypeField::mask()));
__ j(not_zero, miss_label); __ j(not_zero, miss_label);
// Get the value at the masked, scaled index. // Get the value at the masked, scaled index.
const int kValueOffset = kElementsStartOffset + kPointerSize; const int kValueOffset = kElementsStartOffset + kPointerSize;
__ movq(r1, __ movq(r1,
Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag));
} }
...@@ -501,6 +503,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { ...@@ -501,6 +503,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
rcx, rcx,
rdx, rdx,
rax, rax,
rdi,
DICTIONARY_CHECK_DONE); DICTIONARY_CHECK_DONE);
__ movq(rax, rcx); __ movq(rax, rcx);
__ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
...@@ -1228,7 +1231,7 @@ static void GenerateNormalHelper(MacroAssembler* masm, ...@@ -1228,7 +1231,7 @@ static void GenerateNormalHelper(MacroAssembler* masm,
// rsp[(argc + 1) * 8] : argument 0 = receiver // rsp[(argc + 1) * 8] : argument 0 = receiver
// ----------------------------------- // -----------------------------------
// Search dictionary - put result in register rdx. // Search dictionary - put result in register rdx.
GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY); GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, rdi, CHECK_DICTIONARY);
// Move the result to register rdi and check that it isn't a smi. // Move the result to register rdi and check that it isn't a smi.
__ movq(rdi, rdx); __ movq(rdi, rdx);
...@@ -1333,13 +1336,13 @@ void LoadIC::ClearInlinedVersion(Address address) { ...@@ -1333,13 +1336,13 @@ void LoadIC::ClearInlinedVersion(Address address) {
void LoadIC::GenerateMiss(MacroAssembler* masm) { void LoadIC::GenerateMiss(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
__ pop(rbx); __ pop(rbx);
__ push(Operand(rsp, 0)); // receiver __ push(rax); // receiver
__ push(rcx); // name __ push(rcx); // name
__ push(rbx); // return address __ push(rbx); // return address
...@@ -1351,14 +1354,12 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) { ...@@ -1351,14 +1354,12 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
void LoadIC::GenerateArrayLength(MacroAssembler* masm) { void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
...@@ -1367,14 +1368,12 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) { ...@@ -1367,14 +1368,12 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
...@@ -1383,13 +1382,11 @@ void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { ...@@ -1383,13 +1382,11 @@ void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
__ movq(rax, Operand(rsp, kPointerSize));
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
NOT_IN_LOOP, NOT_IN_LOOP,
...@@ -1403,14 +1400,12 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { ...@@ -1403,14 +1400,12 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
void LoadIC::GenerateNormal(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss, probe, global; Label miss, probe, global;
__ movq(rax, Operand(rsp, kPointerSize));
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
__ JumpIfSmi(rax, &miss); __ JumpIfSmi(rax, &miss);
...@@ -1432,7 +1427,8 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -1432,7 +1427,8 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
// Search the dictionary placing the result in rax. // Search the dictionary placing the result in rax.
__ bind(&probe); __ bind(&probe);
GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx, rcx, CHECK_DICTIONARY); GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx,
rcx, rdi, CHECK_DICTIONARY);
__ ret(0); __ ret(0);
// Global object access: Check access rights. // Global object access: Check access rights.
...@@ -1440,23 +1436,20 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) { ...@@ -1440,23 +1436,20 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
__ CheckAccessGlobalProxy(rax, rdx, &miss); __ CheckAccessGlobalProxy(rax, rdx, &miss);
__ jmp(&probe); __ jmp(&probe);
// Cache miss: Restore receiver from stack and jump to runtime. // Cache miss: Jump to runtime.
__ bind(&miss); __ bind(&miss);
__ movq(rax, Operand(rsp, 1 * kPointerSize));
GenerateMiss(masm); GenerateMiss(masm);
} }
void LoadIC::GenerateStringLength(MacroAssembler* masm) { void LoadIC::GenerateStringLength(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss);
__ bind(&miss); __ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
......
...@@ -1318,13 +1318,12 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name, ...@@ -1318,13 +1318,12 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
JSObject* holder, JSObject* holder,
AccessorInfo* callback) { AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
Failure* failure = Failure::InternalError(); Failure* failure = Failure::InternalError();
bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx,
callback, name, &miss, &failure); callback, name, &miss, &failure);
...@@ -1343,13 +1342,12 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, ...@@ -1343,13 +1342,12 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
Object* value, Object* value,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss); GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1363,15 +1361,12 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, ...@@ -1363,15 +1361,12 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object, JSObject* object,
JSObject* last) { JSObject* last) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Load receiver.
__ movq(rax, Operand(rsp, kPointerSize));
// Chech that receiver is not a smi. // Chech that receiver is not a smi.
__ JumpIfSmi(rax, &miss); __ JumpIfSmi(rax, &miss);
...@@ -1409,13 +1404,12 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, ...@@ -1409,13 +1404,12 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
__ movq(rax, Operand(rsp, kPointerSize));
GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss); GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1429,16 +1423,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, ...@@ -1429,16 +1423,15 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
LookupResult lookup; LookupResult lookup;
LookupPostInterceptor(holder, name, &lookup); LookupPostInterceptor(holder, name, &lookup);
__ movq(rax, Operand(rsp, kPointerSize));
// TODO(368): Compile in the whole chain: all the interceptors in // TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer. // prototypes and ultimate answer.
GenerateLoadInterceptor(receiver, GenerateLoadInterceptor(receiver,
...@@ -1465,15 +1458,12 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, ...@@ -1465,15 +1458,12 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Get the receiver from the stack.
__ movq(rax, Operand(rsp, kPointerSize));
// If the object is the holder then we know that it's a global // If the object is the holder then we know that it's a global
// object which can only happen for contextual loads. In this case, // object which can only happen for contextual loads. In this case,
// the receiver cannot be a smi. // the receiver cannot be a smi.
...@@ -1485,19 +1475,20 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, ...@@ -1485,19 +1475,20 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss); CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss);
// Get the value from the cell. // Get the value from the cell.
__ Move(rax, Handle<JSGlobalPropertyCell>(cell)); __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
__ movq(rax, FieldOperand(rax, JSGlobalPropertyCell::kValueOffset)); __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted. // Check for deleted property if property can actually be deleted.
if (!is_dont_delete) { if (!is_dont_delete) {
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex); __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
__ j(equal, &miss); __ j(equal, &miss);
} else if (FLAG_debug_code) { } else if (FLAG_debug_code) {
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex); __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
__ Check(not_equal, "DontDelete cells can't contain the hole"); __ Check(not_equal, "DontDelete cells can't contain the hole");
} }
__ IncrementCounter(&Counters::named_load_global_inline, 1); __ IncrementCounter(&Counters::named_load_global_inline, 1);
__ movq(rax, rbx);
__ ret(0); __ ret(0);
__ bind(&miss); __ bind(&miss);
......
...@@ -1072,14 +1072,14 @@ void VirtualFrame::MoveResultsToRegisters(Result* a, ...@@ -1072,14 +1072,14 @@ void VirtualFrame::MoveResultsToRegisters(Result* a,
Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) { Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
// Name and receiver are on the top of the frame. The IC expects // Name and receiver are on the top of the frame. Both are dropped.
// name in rcx and receiver on the stack. It does not drop the // The IC expects name in rcx and receiver in rax.
// receiver.
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
Result name = Pop(); Result name = Pop();
PrepareForCall(1, 0); // One stack arg, not callee-dropped. Result receiver = Pop();
name.ToRegister(rcx); PrepareForCall(0, 0); // One stack arg, not callee-dropped.
name.Unuse(); MoveResultsToRegisters(&name, &receiver, rcx, rax);
return RawCallCodeObject(ic, mode); return RawCallCodeObject(ic, mode);
} }
......
...@@ -44,16 +44,11 @@ assertEquals(42, x); ...@@ -44,16 +44,11 @@ assertEquals(42, x);
assertTrue(delete x); assertTrue(delete x);
assertTrue(typeof x === 'undefined', "x is gone"); assertTrue(typeof x === 'undefined', "x is gone");
/****
* This test relies on DontDelete attributes. This is not
* working yet.
var y = 87; // should have DontDelete attribute var y = 87; // should have DontDelete attribute
assertEquals(87, y); assertEquals(87, y);
assertFalse(delete y, "don't delete"); assertFalse(delete y, "don't delete");
assertFalse(typeof y === 'undefined'); assertFalse(typeof y === 'undefined');
assertEquals(87, y); assertEquals(87, y);
*/
var o = { x: 42, y: 87 }; var o = { x: 42, y: 87 };
assertTrue(has(o, 'x')); assertTrue(has(o, 'x'));
...@@ -161,3 +156,25 @@ assertFalse(has(a, 1), "delete 1"); ...@@ -161,3 +156,25 @@ assertFalse(has(a, 1), "delete 1");
assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1"); assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1");
assertFalse(has(a, Math.pow(2,31)-1), "delete 2^31-1"); assertFalse(has(a, Math.pow(2,31)-1), "delete 2^31-1");
assertEquals(Math.pow(2,31), a.length); assertEquals(Math.pow(2,31), a.length);
// Check that a LoadIC for a dictionary field works, even
// when the dictionary probe misses.
function load_deleted_property_using_IC() {
var x = new Object();
x.a = 3;
x.b = 4;
x.c = 5;
delete x.c;
assertEquals(3, load_a(x));
assertEquals(3, load_a(x));
delete x.a;
assertTrue(typeof load_a(x) === 'undefined', "x.a is gone");
assertTrue(typeof load_a(x) === 'undefined', "x.a is gone");
}
function load_a(x) {
return x.a;
}
load_deleted_property_using_IC();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment