Chromium Code Reviews| 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); |