Index: src/ia32/codegen-ia32.cc |
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc |
index 86f3877c7e8cdc824793c7956363be47e3fa34c6..738450d2d7bef1353a1f43bb34104fca8c8a6095 100644 |
--- a/src/ia32/codegen-ia32.cc |
+++ b/src/ia32/codegen-ia32.cc |
@@ -9144,9 +9144,15 @@ class DeferredReferenceGetNamedValue: public DeferredCode { |
public: |
DeferredReferenceGetNamedValue(Register dst, |
Register receiver, |
- Handle<String> name) |
- : dst_(dst), receiver_(receiver), name_(name) { |
- set_comment("[ DeferredReferenceGetNamedValue"); |
+ Handle<String> name, |
+ bool is_contextual) |
+ : dst_(dst), |
+ receiver_(receiver), |
+ name_(name), |
+ is_contextual_(is_contextual) { |
+ set_comment(is_contextual |
+ ? "[ DeferredReferenceGetNamedValue (contextual)" |
+ : "[ DeferredReferenceGetNamedValue"); |
} |
virtual void Generate(); |
@@ -9158,6 +9164,7 @@ class DeferredReferenceGetNamedValue: public DeferredCode { |
Register dst_; |
Register receiver_; |
Handle<String> name_; |
+ bool is_contextual_; |
}; |
@@ -9167,9 +9174,15 @@ void DeferredReferenceGetNamedValue::Generate() { |
} |
__ Set(ecx, Immediate(name_)); |
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
- __ call(ic, RelocInfo::CODE_TARGET); |
- // The call must be followed by a test eax instruction to indicate |
- // that the inobject property case was inlined. |
+ RelocInfo::Mode mode = is_contextual_ |
+ ? RelocInfo::CODE_TARGET_CONTEXT |
+ : RelocInfo::CODE_TARGET; |
+ __ call(ic, mode); |
+ // The call must be followed by: |
+ // - a test eax instruction to indicate that the inobject property |
+ // case was inlined. |
+ // - a mov ecx instruction to indicate that the contextual property |
+ // load was inlined. |
// |
// Store the delta to the map check instruction here in the test |
// instruction. Use masm_-> instead of the __ macro since the |
@@ -9177,8 +9190,13 @@ void DeferredReferenceGetNamedValue::Generate() { |
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
// Here we use masm_-> instead of the __ macro because this is the |
// instruction that gets patched and coverage code gets in the way. |
- masm_->test(eax, Immediate(-delta_to_patch_site)); |
- __ IncrementCounter(&Counters::named_load_inline_miss, 1); |
+ if (is_contextual_) { |
+ masm_->mov(ecx, -delta_to_patch_site); |
+ __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); |
+ } else { |
+ masm_->test(eax, Immediate(-delta_to_patch_site)); |
+ __ IncrementCounter(&Counters::named_load_inline_miss, 1); |
+ } |
if (!dst_.is(eax)) __ mov(dst_, eax); |
} |
@@ -9349,12 +9367,17 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
#ifdef DEBUG |
int original_height = frame()->height(); |
#endif |
+ |
+ bool contextual_load_in_builtin = |
+ is_contextual && |
+ (Bootstrapper::IsActive() || |
+ (!info_->closure().is_null() && info_->closure()->IsBuiltin())); |
+ |
Result result; |
- // Do not inline the inobject property case for loads from the global |
- // object. Also do not inline for unoptimized code. This saves time in |
- // the code generator. Unoptimized code is toplevel code or code that is |
- // not in a loop. |
- if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
+ // Do not inline in the global code or when not in loop. |
+ if (scope()->is_global_scope() || |
+ loop_nesting() == 0 || |
+ contextual_load_in_builtin) { |
Comment cmnt(masm(), "[ Load from named Property"); |
frame()->Push(name); |
@@ -9367,19 +9390,26 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
// instruction here. |
__ nop(); |
} else { |
- // Inline the inobject property case. |
- Comment cmnt(masm(), "[ Inlined named property load"); |
+ // Inline the property load. |
+ Comment cmnt(masm(), is_contextual |
+ ? "[ Inlined contextual property load" |
+ : "[ Inlined named property load"); |
Result receiver = frame()->Pop(); |
receiver.ToRegister(); |
result = allocator()->Allocate(); |
ASSERT(result.is_valid()); |
DeferredReferenceGetNamedValue* deferred = |
- new DeferredReferenceGetNamedValue(result.reg(), receiver.reg(), name); |
+ new DeferredReferenceGetNamedValue(result.reg(), |
+ receiver.reg(), |
+ name, |
+ is_contextual); |
- // Check that the receiver is a heap object. |
- __ test(receiver.reg(), Immediate(kSmiTagMask)); |
- deferred->Branch(zero); |
+ if (!is_contextual) { |
+ // Check that the receiver is a heap object. |
+ __ test(receiver.reg(), Immediate(kSmiTagMask)); |
+ deferred->Branch(zero); |
+ } |
__ bind(deferred->patch_site()); |
// This is the map check instruction that will be patched (so we can't |
@@ -9391,17 +9421,28 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
// which allows the assert below to succeed and patching to work. |
deferred->Branch(not_equal); |
- // The delta from the patch label to the load offset must be statically |
- // known. |
+ // The delta from the patch label to the actual load must be |
+ // statically known. |
ASSERT(masm()->SizeOfCodeGeneratedSince(deferred->patch_site()) == |
LoadIC::kOffsetToLoadInstruction); |
- // The initial (invalid) offset has to be large enough to force a 32-bit |
- // instruction encoding to allow patching with an arbitrary offset. Use |
- // kMaxInt (minus kHeapObjectTag). |
- int offset = kMaxInt; |
- masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset)); |
- __ IncrementCounter(&Counters::named_load_inline, 1); |
+ if (is_contextual) { |
+ // Load the (initialy invalid) cell and get its value. |
+ masm()->mov(result.reg(), Factory::null_value()); |
Søren Thygesen Gjesse
2010/09/20 06:50:08
How about having a --debug-code guarded assert her
|
+ __ mov(result.reg(), |
+ FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset)); |
+ __ cmp(result.reg(), Factory::the_hole_value()); |
+ deferred->Branch(equal); |
+ __ IncrementCounter(&Counters::named_load_global_inline, 1); |
+ } else { |
+ // The initial (invalid) offset has to be large enough to force a 32-bit |
+ // instruction encoding to allow patching with an arbitrary offset. Use |
+ // kMaxInt (minus kHeapObjectTag). |
+ int offset = kMaxInt; |
+ masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset)); |
+ __ IncrementCounter(&Counters::named_load_inline, 1); |
+ } |
+ |
deferred->BindExit(); |
} |
ASSERT(frame()->height() == original_height - 1); |