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

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

Issue 99120: Inline the inobject property case for named property loads. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "ic-inl.h"
33 #include "parser.h" 34 #include "parser.h"
34 #include "register-allocator-inl.h" 35 #include "register-allocator-inl.h"
35 #include "runtime.h" 36 #include "runtime.h"
36 #include "scopes.h" 37 #include "scopes.h"
37 38
38 namespace v8 { namespace internal { 39 namespace v8 { namespace internal {
39 40
40 #define __ ACCESS_MASM(masm_) 41 #define __ ACCESS_MASM(masm_)
41 42
42 // ------------------------------------------------------------------------- 43 // -------------------------------------------------------------------------
(...skipping 3360 matching lines...) Expand 10 before | Expand all | Expand 10 after
3403 tmp.Unuse(); 3404 tmp.Unuse();
3404 3405
3405 // All extension objects were empty and it is safe to use a global 3406 // All extension objects were empty and it is safe to use a global
3406 // load IC call. 3407 // load IC call.
3407 LoadGlobal(); 3408 LoadGlobal();
3408 frame_->Push(slot->var()->name()); 3409 frame_->Push(slot->var()->name());
3409 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 3410 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
3410 ? RelocInfo::CODE_TARGET 3411 ? RelocInfo::CODE_TARGET
3411 : RelocInfo::CODE_TARGET_CONTEXT; 3412 : RelocInfo::CODE_TARGET_CONTEXT;
3412 Result answer = frame_->CallLoadIC(mode); 3413 Result answer = frame_->CallLoadIC(mode);
3413 3414 // A test eax instruction following the call signals that the inobject
3415 // property case was inlined. Ensure that there is not a test eax
3416 // instruction here.
3417 __ nop();
3414 // Discard the global object. The result is in answer. 3418 // Discard the global object. The result is in answer.
3415 frame_->Drop(); 3419 frame_->Drop();
3416 return answer; 3420 return answer;
3417 } 3421 }
3418 3422
3419 3423
3420 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 3424 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
3421 if (slot->type() == Slot::LOOKUP) { 3425 if (slot->type() == Slot::LOOKUP) {
3422 ASSERT(slot->var()->is_dynamic()); 3426 ASSERT(slot->var()->is_dynamic());
3423 3427
(...skipping 1802 matching lines...) Expand 10 before | Expand all | Expand 10 after
5226 bool CodeGenerator::HasValidEntryRegisters() { 5230 bool CodeGenerator::HasValidEntryRegisters() {
5227 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) 5231 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0))
5228 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) 5232 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
5229 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) 5233 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
5230 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) 5234 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
5231 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); 5235 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0));
5232 } 5236 }
5233 #endif 5237 #endif
5234 5238
5235 5239
5240 class DeferredReferenceGetNamedValue: public DeferredCode {
5241 public:
5242 DeferredReferenceGetNamedValue(CodeGenerator* cgen, Handle<String> name)
5243 : DeferredCode(cgen), name_(name) {
5244 set_comment("[ DeferredReferenceGetNamedValue");
5245 }
5246
5247 virtual void Generate();
5248
5249 Label* patch_site() { return &patch_site_; }
5250
5251 private:
5252 Label patch_site_;
5253 Handle<String> name_;
5254 };
5255
5256
5257 void DeferredReferenceGetNamedValue::Generate() {
5258 CodeGenerator* cgen = generator();
5259 Result receiver(cgen);
5260 enter()->Bind(&receiver);
5261
5262 cgen->frame()->Push(&receiver);
5263 cgen->frame()->Push(name_);
5264 Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
5265 // The call must be followed by a test eax instruction to indicate
5266 // that the inobject property case was inlined.
5267 ASSERT(answer.is_register() && answer.reg().is(eax));
5268 // Store the delta to the map check instruction here in the test
5269 // instruction.
5270 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
5271 // Here we use masm_-> instead of the double underscore macro because
5272 // this is the instruction that gets patched and coverage code gets in
5273 // the way.
5274 masm_->test(answer.reg(), Immediate(-delta_to_patch_site));
5275 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
5276 receiver = cgen->frame()->Pop();
5277 exit_.Jump(&receiver, &answer);
5278 }
5279
5280
5236 class DeferredReferenceGetKeyedValue: public DeferredCode { 5281 class DeferredReferenceGetKeyedValue: public DeferredCode {
5237 public: 5282 public:
5238 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) 5283 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
5239 : DeferredCode(generator), is_global_(is_global) { 5284 : DeferredCode(generator), is_global_(is_global) {
5240 set_comment("[ DeferredReferenceGetKeyedValue"); 5285 set_comment("[ DeferredReferenceGetKeyedValue");
5241 } 5286 }
5242 5287
5243 virtual void Generate(); 5288 virtual void Generate();
5244 5289
5245 Label* patch_site() { return &patch_site_; } 5290 Label* patch_site() { return &patch_site_; }
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
5327 break; 5372 break;
5328 } 5373 }
5329 5374
5330 case NAMED: { 5375 case NAMED: {
5331 // TODO(1241834): Make sure that it is safe to ignore the 5376 // TODO(1241834): Make sure that it is safe to ignore the
5332 // distinction between expressions in a typeof and not in a 5377 // distinction between expressions in a typeof and not in a
5333 // typeof. If there is a chance that reference errors can be 5378 // typeof. If there is a chance that reference errors can be
5334 // thrown below, we must distinguish between the two kinds of 5379 // thrown below, we must distinguish between the two kinds of
5335 // loads (typeof expression loads must not throw a reference 5380 // loads (typeof expression loads must not throw a reference
5336 // error). 5381 // error).
5337 Comment cmnt(masm, "[ Load from named Property"); 5382 Variable* var = expression_->AsVariableProxy()->AsVariable();
5338 cgen_->frame()->Push(GetName()); 5383 bool is_global = var != NULL;
5384 ASSERT(!is_global || var->is_global());
5339 5385
5340 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5386 if (is_global || cgen_->scope()->is_global_scope()) {
5341 ASSERT(var == NULL || var->is_global()); 5387 // Do not inline the inobject property case for loads from the
5342 RelocInfo::Mode mode = (var == NULL) 5388 // global object or loads in toplevel code.
5343 ? RelocInfo::CODE_TARGET 5389 Comment cmnt(masm, "[ Load from named Property");
5344 : RelocInfo::CODE_TARGET_CONTEXT; 5390 cgen_->frame()->Push(GetName());
5345 Result answer = cgen_->frame()->CallLoadIC(mode); 5391
5346 cgen_->frame()->Push(&answer); 5392 RelocInfo::Mode mode = is_global
5393 ? RelocInfo::CODE_TARGET_CONTEXT
5394 : RelocInfo::CODE_TARGET;
5395 Result answer = cgen_->frame()->CallLoadIC(mode);
5396 // A test eax instruction following the call signals that the
5397 // inobject property case was inlined. Ensure that there is not
5398 // a test eax instruction here.
5399 __ nop();
5400 cgen_->frame()->Push(&answer);
5401 } else {
5402 // Inline the inobject property case.
5403 Comment cmnt(masm, "[ Inlined named property load");
5404 DeferredReferenceGetNamedValue* deferred =
5405 new DeferredReferenceGetNamedValue(cgen_, GetName());
5406 Result receiver = cgen_->frame()->Pop();
5407 receiver.ToRegister();
5408 // Check that the receiver is a heap object.
5409 __ test(receiver.reg(), Immediate(kSmiTagMask));
5410 deferred->enter()->Branch(zero, &receiver, not_taken);
5411
5412 // Preallocate the value register to ensure that there is no
5413 // spill emitted between the patch site label and the offset in
5414 // the load instruction.
5415 Result value = cgen_->allocator()->Allocate();
5416 ASSERT(value.is_valid());
5417 __ bind(deferred->patch_site());
5418 // This is the map chack instruction that will be patched.
5419 // Initially use an invalid map to force a failure.
5420 __ cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
5421 Immediate(Factory::null_value()));
5422 deferred->enter()->Branch(not_equal, &receiver, not_taken);
5423
5424 // The delta from the patch label to the load offset must be
5425 // statically known.
5426 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
5427 LoadIC::kOffsetToLoadInstruction);
5428 // The initial (invalid) offset has to be large enough to force
5429 // a 32-bit instruction encoding to allow patching with an
5430 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
5431 int offset = kMaxInt;
5432 __ mov(value.reg(), FieldOperand(receiver.reg(), offset));
5433
5434 __ IncrementCounter(&Counters::named_load_inline, 1);
5435 deferred->BindExit(&receiver, &value);
5436 cgen_->frame()->Push(&receiver);
5437 cgen_->frame()->Push(&value);
5438 }
5347 break; 5439 break;
5348 } 5440 }
5349 5441
5350 case KEYED: { 5442 case KEYED: {
5351 // TODO(1241834): Make sure that this it is safe to ignore the 5443 // TODO(1241834): Make sure that this it is safe to ignore the
5352 // distinction between expressions in a typeof and not in a typeof. 5444 // distinction between expressions in a typeof and not in a typeof.
5353 Comment cmnt(masm, "[ Load from keyed Property"); 5445 Comment cmnt(masm, "[ Load from keyed Property");
5354 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5446 Variable* var = expression_->AsVariableProxy()->AsVariable();
5355 bool is_global = var != NULL; 5447 bool is_global = var != NULL;
5356 ASSERT(!is_global || var->is_global()); 5448 ASSERT(!is_global || var->is_global());
(...skipping 1764 matching lines...) Expand 10 before | Expand all | Expand 10 after
7121 7213
7122 // Slow-case: Go through the JavaScript implementation. 7214 // Slow-case: Go through the JavaScript implementation.
7123 __ bind(&slow); 7215 __ bind(&slow);
7124 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7216 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7125 } 7217 }
7126 7218
7127 7219
7128 #undef __ 7220 #undef __
7129 7221
7130 } } // namespace v8::internal 7222 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.cc ('k') | src/ia32/ic-ia32.cc » ('j') | src/ia32/ic-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698