Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1689)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 3402014: Generate inline code for contextual loads. (Closed)
Patch Set: Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/frames.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 9126 matching lines...) Expand 10 before | Expand all | Expand 10 after
9137 } 9137 }
9138 #endif 9138 #endif
9139 9139
9140 9140
9141 // Emit a LoadIC call to get the value from receiver and leave it in 9141 // Emit a LoadIC call to get the value from receiver and leave it in
9142 // dst. 9142 // dst.
9143 class DeferredReferenceGetNamedValue: public DeferredCode { 9143 class DeferredReferenceGetNamedValue: public DeferredCode {
9144 public: 9144 public:
9145 DeferredReferenceGetNamedValue(Register dst, 9145 DeferredReferenceGetNamedValue(Register dst,
9146 Register receiver, 9146 Register receiver,
9147 Handle<String> name) 9147 Handle<String> name,
9148 : dst_(dst), receiver_(receiver), name_(name) { 9148 bool is_contextual)
9149 set_comment("[ DeferredReferenceGetNamedValue"); 9149 : dst_(dst),
9150 receiver_(receiver),
9151 name_(name),
9152 is_contextual_(is_contextual) {
9153 set_comment(is_contextual
9154 ? "[ DeferredReferenceGetNamedValue (contextual)"
9155 : "[ DeferredReferenceGetNamedValue");
9150 } 9156 }
9151 9157
9152 virtual void Generate(); 9158 virtual void Generate();
9153 9159
9154 Label* patch_site() { return &patch_site_; } 9160 Label* patch_site() { return &patch_site_; }
9155 9161
9156 private: 9162 private:
9157 Label patch_site_; 9163 Label patch_site_;
9158 Register dst_; 9164 Register dst_;
9159 Register receiver_; 9165 Register receiver_;
9160 Handle<String> name_; 9166 Handle<String> name_;
9167 bool is_contextual_;
9161 }; 9168 };
9162 9169
9163 9170
9164 void DeferredReferenceGetNamedValue::Generate() { 9171 void DeferredReferenceGetNamedValue::Generate() {
9165 if (!receiver_.is(eax)) { 9172 if (!receiver_.is(eax)) {
9166 __ mov(eax, receiver_); 9173 __ mov(eax, receiver_);
9167 } 9174 }
9168 __ Set(ecx, Immediate(name_)); 9175 __ Set(ecx, Immediate(name_));
9169 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 9176 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
9170 __ call(ic, RelocInfo::CODE_TARGET); 9177 RelocInfo::Mode mode = is_contextual_
9171 // The call must be followed by a test eax instruction to indicate 9178 ? RelocInfo::CODE_TARGET_CONTEXT
9172 // that the inobject property case was inlined. 9179 : RelocInfo::CODE_TARGET;
9180 __ call(ic, mode);
9181 // The call must be followed by:
9182 // - a test eax instruction to indicate that the inobject property
9183 // case was inlined.
9184 // - a mov ecx instruction to indicate that the contextual property
9185 // load was inlined.
9173 // 9186 //
9174 // Store the delta to the map check instruction here in the test 9187 // Store the delta to the map check instruction here in the test
9175 // instruction. Use masm_-> instead of the __ macro since the 9188 // instruction. Use masm_-> instead of the __ macro since the
9176 // latter can't return a value. 9189 // latter can't return a value.
9177 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 9190 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
9178 // Here we use masm_-> instead of the __ macro because this is the 9191 // Here we use masm_-> instead of the __ macro because this is the
9179 // instruction that gets patched and coverage code gets in the way. 9192 // instruction that gets patched and coverage code gets in the way.
9180 masm_->test(eax, Immediate(-delta_to_patch_site)); 9193 if (is_contextual_) {
9181 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 9194 masm_->mov(ecx, -delta_to_patch_site);
9195 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
9196 } else {
9197 masm_->test(eax, Immediate(-delta_to_patch_site));
9198 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
9199 }
9182 9200
9183 if (!dst_.is(eax)) __ mov(dst_, eax); 9201 if (!dst_.is(eax)) __ mov(dst_, eax);
9184 } 9202 }
9185 9203
9186 9204
9187 class DeferredReferenceGetKeyedValue: public DeferredCode { 9205 class DeferredReferenceGetKeyedValue: public DeferredCode {
9188 public: 9206 public:
9189 explicit DeferredReferenceGetKeyedValue(Register dst, 9207 explicit DeferredReferenceGetKeyedValue(Register dst,
9190 Register receiver, 9208 Register receiver,
9191 Register key) 9209 Register key)
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
9342 masm_->test(eax, Immediate(-delta_to_patch_site)); 9360 masm_->test(eax, Immediate(-delta_to_patch_site));
9343 // Restore value (returned from store IC) register. 9361 // Restore value (returned from store IC) register.
9344 if (!old_value.is(eax)) __ mov(old_value, eax); 9362 if (!old_value.is(eax)) __ mov(old_value, eax);
9345 } 9363 }
9346 9364
9347 9365
9348 Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { 9366 Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
9349 #ifdef DEBUG 9367 #ifdef DEBUG
9350 int original_height = frame()->height(); 9368 int original_height = frame()->height();
9351 #endif 9369 #endif
9370
9371 bool contextual_load_in_builtin =
9372 is_contextual &&
9373 (Bootstrapper::IsActive() ||
9374 (!info_->closure().is_null() && info_->closure()->IsBuiltin()));
9375
9352 Result result; 9376 Result result;
9353 // Do not inline the inobject property case for loads from the global 9377 // Do not inline in the global code or when not in loop.
9354 // object. Also do not inline for unoptimized code. This saves time in 9378 if (scope()->is_global_scope() ||
9355 // the code generator. Unoptimized code is toplevel code or code that is 9379 loop_nesting() == 0 ||
9356 // not in a loop. 9380 contextual_load_in_builtin) {
9357 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
9358 Comment cmnt(masm(), "[ Load from named Property"); 9381 Comment cmnt(masm(), "[ Load from named Property");
9359 frame()->Push(name); 9382 frame()->Push(name);
9360 9383
9361 RelocInfo::Mode mode = is_contextual 9384 RelocInfo::Mode mode = is_contextual
9362 ? RelocInfo::CODE_TARGET_CONTEXT 9385 ? RelocInfo::CODE_TARGET_CONTEXT
9363 : RelocInfo::CODE_TARGET; 9386 : RelocInfo::CODE_TARGET;
9364 result = frame()->CallLoadIC(mode); 9387 result = frame()->CallLoadIC(mode);
9365 // A test eax instruction following the call signals that the inobject 9388 // A test eax instruction following the call signals that the inobject
9366 // property case was inlined. Ensure that there is not a test eax 9389 // property case was inlined. Ensure that there is not a test eax
9367 // instruction here. 9390 // instruction here.
9368 __ nop(); 9391 __ nop();
9369 } else { 9392 } else {
9370 // Inline the inobject property case. 9393 // Inline the property load.
9371 Comment cmnt(masm(), "[ Inlined named property load"); 9394 Comment cmnt(masm(), is_contextual
9395 ? "[ Inlined contextual property load"
9396 : "[ Inlined named property load");
9372 Result receiver = frame()->Pop(); 9397 Result receiver = frame()->Pop();
9373 receiver.ToRegister(); 9398 receiver.ToRegister();
9374 9399
9375 result = allocator()->Allocate(); 9400 result = allocator()->Allocate();
9376 ASSERT(result.is_valid()); 9401 ASSERT(result.is_valid());
9377 DeferredReferenceGetNamedValue* deferred = 9402 DeferredReferenceGetNamedValue* deferred =
9378 new DeferredReferenceGetNamedValue(result.reg(), receiver.reg(), name); 9403 new DeferredReferenceGetNamedValue(result.reg(),
9404 receiver.reg(),
9405 name,
9406 is_contextual);
9379 9407
9380 // Check that the receiver is a heap object. 9408 if (!is_contextual) {
9381 __ test(receiver.reg(), Immediate(kSmiTagMask)); 9409 // Check that the receiver is a heap object.
9382 deferred->Branch(zero); 9410 __ test(receiver.reg(), Immediate(kSmiTagMask));
9411 deferred->Branch(zero);
9412 }
9383 9413
9384 __ bind(deferred->patch_site()); 9414 __ bind(deferred->patch_site());
9385 // This is the map check instruction that will be patched (so we can't 9415 // This is the map check instruction that will be patched (so we can't
9386 // use the double underscore macro that may insert instructions). 9416 // use the double underscore macro that may insert instructions).
9387 // Initially use an invalid map to force a failure. 9417 // Initially use an invalid map to force a failure.
9388 masm()->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 9418 masm()->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
9389 Immediate(Factory::null_value())); 9419 Immediate(Factory::null_value()));
9390 // This branch is always a forwards branch so it's always a fixed size 9420 // This branch is always a forwards branch so it's always a fixed size
9391 // which allows the assert below to succeed and patching to work. 9421 // which allows the assert below to succeed and patching to work.
9392 deferred->Branch(not_equal); 9422 deferred->Branch(not_equal);
9393 9423
9394 // The delta from the patch label to the load offset must be statically 9424 // The delta from the patch label to the actual load must be
9395 // known. 9425 // statically known.
9396 ASSERT(masm()->SizeOfCodeGeneratedSince(deferred->patch_site()) == 9426 ASSERT(masm()->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
9397 LoadIC::kOffsetToLoadInstruction); 9427 LoadIC::kOffsetToLoadInstruction);
9398 // The initial (invalid) offset has to be large enough to force a 32-bit
9399 // instruction encoding to allow patching with an arbitrary offset. Use
9400 // kMaxInt (minus kHeapObjectTag).
9401 int offset = kMaxInt;
9402 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset));
9403 9428
9404 __ IncrementCounter(&Counters::named_load_inline, 1); 9429 if (is_contextual) {
9430 // Load the (initialy invalid) cell and get its value.
9431 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
9432 __ mov(result.reg(),
9433 FieldOperand(result.reg(), JSGlobalPropertyCell::kValueOffset));
9434 __ cmp(result.reg(), Factory::the_hole_value());
9435 deferred->Branch(equal);
9436 __ IncrementCounter(&Counters::named_load_global_inline, 1);
9437 } else {
9438 // The initial (invalid) offset has to be large enough to force a 32-bit
9439 // instruction encoding to allow patching with an arbitrary offset. Use
9440 // kMaxInt (minus kHeapObjectTag).
9441 int offset = kMaxInt;
9442 masm()->mov(result.reg(), FieldOperand(receiver.reg(), offset));
9443 __ IncrementCounter(&Counters::named_load_inline, 1);
9444 }
9445
9405 deferred->BindExit(); 9446 deferred->BindExit();
9406 } 9447 }
9407 ASSERT(frame()->height() == original_height - 1); 9448 ASSERT(frame()->height() == original_height - 1);
9408 return result; 9449 return result;
9409 } 9450 }
9410 9451
9411 9452
9412 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { 9453 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
9413 #ifdef DEBUG 9454 #ifdef DEBUG
9414 int expected_height = frame()->height() - (is_contextual ? 1 : 2); 9455 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
10055 masm.GetCode(&desc); 10096 masm.GetCode(&desc);
10056 // Call the function from C++. 10097 // Call the function from C++.
10057 return FUNCTION_CAST<MemCopyFunction>(buffer); 10098 return FUNCTION_CAST<MemCopyFunction>(buffer);
10058 } 10099 }
10059 10100
10060 #undef __ 10101 #undef __
10061 10102
10062 } } // namespace v8::internal 10103 } } // namespace v8::internal
10063 10104
10064 #endif // V8_TARGET_ARCH_IA32 10105 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698