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

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

Issue 573009: Change LoadIC interface on ia32 to take arguments in registers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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
« no previous file with comments | « src/full-codegen.cc ('k') | src/ia32/debug-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 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after
2320 // just copies y and the arguments of the current function on the 2320 // just copies y and the arguments of the current function on the
2321 // stack, as receiver and arguments, and calls x. 2321 // stack, as receiver and arguments, and calls x.
2322 // In the implementation comments, we call x the applicand 2322 // In the implementation comments, we call x the applicand
2323 // and y the receiver. 2323 // and y the receiver.
2324 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); 2324 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION);
2325 ASSERT(arguments->IsArguments()); 2325 ASSERT(arguments->IsArguments());
2326 2326
2327 // Load applicand.apply onto the stack. This will usually 2327 // Load applicand.apply onto the stack. This will usually
2328 // give us a megamorphic load site. Not super, but it works. 2328 // give us a megamorphic load site. Not super, but it works.
2329 Load(applicand); 2329 Load(applicand);
2330 frame()->Dup();
2330 Handle<String> name = Factory::LookupAsciiSymbol("apply"); 2331 Handle<String> name = Factory::LookupAsciiSymbol("apply");
2331 frame()->Push(name); 2332 frame()->Push(name);
2332 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); 2333 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
2333 __ nop(); 2334 __ nop();
2334 frame()->Push(&answer); 2335 frame()->Push(&answer);
2335 2336
2336 // Load the receiver and the existing arguments object onto the 2337 // Load the receiver and the existing arguments object onto the
2337 // expression stack. Avoid allocating the arguments object here. 2338 // expression stack. Avoid allocating the arguments object here.
2338 Load(receiver); 2339 Load(receiver);
2339 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); 2340 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
(...skipping 1850 matching lines...) Expand 10 before | Expand all | Expand 10 after
4190 LoadGlobal(); 4191 LoadGlobal();
4191 frame_->Push(slot->var()->name()); 4192 frame_->Push(slot->var()->name());
4192 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 4193 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
4193 ? RelocInfo::CODE_TARGET 4194 ? RelocInfo::CODE_TARGET
4194 : RelocInfo::CODE_TARGET_CONTEXT; 4195 : RelocInfo::CODE_TARGET_CONTEXT;
4195 Result answer = frame_->CallLoadIC(mode); 4196 Result answer = frame_->CallLoadIC(mode);
4196 // A test eax instruction following the call signals that the inobject 4197 // A test eax instruction following the call signals that the inobject
4197 // property case was inlined. Ensure that there is not a test eax 4198 // property case was inlined. Ensure that there is not a test eax
4198 // instruction here. 4199 // instruction here.
4199 __ nop(); 4200 __ nop();
4200 // Discard the global object. The result is in answer.
4201 frame_->Drop();
4202 return answer; 4201 return answer;
4203 } 4202 }
4204 4203
4205 4204
4206 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 4205 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
4207 if (slot->type() == Slot::LOOKUP) { 4206 if (slot->type() == Slot::LOOKUP) {
4208 ASSERT(slot->var()->is_dynamic()); 4207 ASSERT(slot->var()->is_dynamic());
4209 4208
4210 // For now, just do a runtime call. Since the call is inevitable, 4209 // For now, just do a runtime call. Since the call is inevitable,
4211 // we eagerly sync the virtual frame so we can directly push the 4210 // we eagerly sync the virtual frame so we can directly push the
(...skipping 2057 matching lines...) Expand 10 before | Expand all | Expand 10 after
6269 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) 6268 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0))
6270 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) 6269 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
6271 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) 6270 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
6272 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) 6271 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
6273 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); 6272 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0));
6274 } 6273 }
6275 #endif 6274 #endif
6276 6275
6277 6276
6278 // Emit a LoadIC call to get the value from receiver and leave it in 6277 // Emit a LoadIC call to get the value from receiver and leave it in
6279 // dst. The receiver register is restored after the call. 6278 // dst.
6280 class DeferredReferenceGetNamedValue: public DeferredCode { 6279 class DeferredReferenceGetNamedValue: public DeferredCode {
6281 public: 6280 public:
6282 DeferredReferenceGetNamedValue(Register dst, 6281 DeferredReferenceGetNamedValue(Register dst,
6283 Register receiver, 6282 Register receiver,
6284 Handle<String> name) 6283 Handle<String> name)
6285 : dst_(dst), receiver_(receiver), name_(name) { 6284 : dst_(dst), receiver_(receiver), name_(name) {
6286 set_comment("[ DeferredReferenceGetNamedValue"); 6285 set_comment("[ DeferredReferenceGetNamedValue");
6287 } 6286 }
6288 6287
6289 virtual void Generate(); 6288 virtual void Generate();
6290 6289
6291 Label* patch_site() { return &patch_site_; } 6290 Label* patch_site() { return &patch_site_; }
6292 6291
6293 private: 6292 private:
6294 Label patch_site_; 6293 Label patch_site_;
6295 Register dst_; 6294 Register dst_;
6296 Register receiver_; 6295 Register receiver_;
6297 Handle<String> name_; 6296 Handle<String> name_;
6298 }; 6297 };
6299 6298
6300 6299
6301 void DeferredReferenceGetNamedValue::Generate() { 6300 void DeferredReferenceGetNamedValue::Generate() {
6302 __ push(receiver_); 6301 if (!receiver_.is(eax)) {
6302 __ mov(eax, receiver_);
6303 }
6303 __ Set(ecx, Immediate(name_)); 6304 __ Set(ecx, Immediate(name_));
6304 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 6305 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
6305 __ call(ic, RelocInfo::CODE_TARGET); 6306 __ call(ic, RelocInfo::CODE_TARGET);
6306 // The call must be followed by a test eax instruction to indicate 6307 // The call must be followed by a test eax instruction to indicate
6307 // that the inobject property case was inlined. 6308 // that the inobject property case was inlined.
6308 // 6309 //
6309 // Store the delta to the map check instruction here in the test 6310 // Store the delta to the map check instruction here in the test
6310 // instruction. Use masm_-> instead of the __ macro since the 6311 // instruction. Use masm_-> instead of the __ macro since the
6311 // latter can't return a value. 6312 // latter can't return a value.
6312 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 6313 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
6313 // Here we use masm_-> instead of the __ macro because this is the 6314 // Here we use masm_-> instead of the __ macro because this is the
6314 // instruction that gets patched and coverage code gets in the way. 6315 // instruction that gets patched and coverage code gets in the way.
6315 masm_->test(eax, Immediate(-delta_to_patch_site)); 6316 masm_->test(eax, Immediate(-delta_to_patch_site));
6316 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 6317 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
6317 6318
6318 if (!dst_.is(eax)) __ mov(dst_, eax); 6319 if (!dst_.is(eax)) __ mov(dst_, eax);
6319 __ pop(receiver_);
6320 } 6320 }
6321 6321
6322 6322
6323 class DeferredReferenceGetKeyedValue: public DeferredCode { 6323 class DeferredReferenceGetKeyedValue: public DeferredCode {
6324 public: 6324 public:
6325 explicit DeferredReferenceGetKeyedValue(Register dst, 6325 explicit DeferredReferenceGetKeyedValue(Register dst,
6326 Register receiver, 6326 Register receiver,
6327 Register key, 6327 Register key,
6328 bool is_global) 6328 bool is_global)
6329 : dst_(dst), receiver_(receiver), key_(key), is_global_(is_global) { 6329 : dst_(dst), receiver_(receiver), key_(key), is_global_(is_global) {
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
6563 if (property != NULL) { 6563 if (property != NULL) {
6564 cgen_->CodeForSourcePosition(property->position()); 6564 cgen_->CodeForSourcePosition(property->position());
6565 } 6565 }
6566 6566
6567 switch (type_) { 6567 switch (type_) {
6568 case SLOT: { 6568 case SLOT: {
6569 Comment cmnt(masm, "[ Load from Slot"); 6569 Comment cmnt(masm, "[ Load from Slot");
6570 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 6570 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
6571 ASSERT(slot != NULL); 6571 ASSERT(slot != NULL);
6572 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); 6572 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
6573 if (!persist_after_get_) {
6574 cgen_->UnloadReference(this);
6575 }
6573 break; 6576 break;
6574 } 6577 }
6575 6578
6576 case NAMED: { 6579 case NAMED: {
6577 Variable* var = expression_->AsVariableProxy()->AsVariable(); 6580 Variable* var = expression_->AsVariableProxy()->AsVariable();
6578 bool is_global = var != NULL; 6581 bool is_global = var != NULL;
6579 ASSERT(!is_global || var->is_global()); 6582 ASSERT(!is_global || var->is_global());
6580 6583
6584 if (persist_after_get_) {
6585 cgen_->frame()->Dup();
6586 }
6581 // Do not inline the inobject property case for loads from the global 6587 // Do not inline the inobject property case for loads from the global
6582 // object. Also do not inline for unoptimized code. This saves time 6588 // object. Also do not inline for unoptimized code. This saves time
6583 // in the code generator. Unoptimized code is toplevel code or code 6589 // in the code generator. Unoptimized code is toplevel code or code
6584 // that is not in a loop. 6590 // that is not in a loop.
6585 if (is_global || 6591 if (is_global ||
6586 cgen_->scope()->is_global_scope() || 6592 cgen_->scope()->is_global_scope() ||
6587 cgen_->loop_nesting() == 0) { 6593 cgen_->loop_nesting() == 0) {
6588 Comment cmnt(masm, "[ Load from named Property"); 6594 Comment cmnt(masm, "[ Load from named Property");
6589 cgen_->frame()->Push(GetName()); 6595 cgen_->frame()->Push(GetName());
6590 6596
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
6629 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) == 6635 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
6630 LoadIC::kOffsetToLoadInstruction); 6636 LoadIC::kOffsetToLoadInstruction);
6631 // The initial (invalid) offset has to be large enough to force 6637 // The initial (invalid) offset has to be large enough to force
6632 // a 32-bit instruction encoding to allow patching with an 6638 // a 32-bit instruction encoding to allow patching with an
6633 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). 6639 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
6634 int offset = kMaxInt; 6640 int offset = kMaxInt;
6635 masm->mov(value.reg(), FieldOperand(receiver.reg(), offset)); 6641 masm->mov(value.reg(), FieldOperand(receiver.reg(), offset));
6636 6642
6637 __ IncrementCounter(&Counters::named_load_inline, 1); 6643 __ IncrementCounter(&Counters::named_load_inline, 1);
6638 deferred->BindExit(); 6644 deferred->BindExit();
6639 cgen_->frame()->Push(&receiver);
6640 cgen_->frame()->Push(&value); 6645 cgen_->frame()->Push(&value);
6641 } 6646 }
6647 if (!persist_after_get_) {
6648 set_unloaded();
6649 }
6642 break; 6650 break;
6643 } 6651 }
6644 6652
6645 case KEYED: { 6653 case KEYED: {
6646 Variable* var = expression_->AsVariableProxy()->AsVariable(); 6654 Variable* var = expression_->AsVariableProxy()->AsVariable();
6647 bool is_global = var != NULL; 6655 bool is_global = var != NULL;
6648 ASSERT(!is_global || var->is_global()); 6656 ASSERT(!is_global || var->is_global());
6649 Result value = cgen_->EmitKeyedLoad(is_global); 6657 Result value = cgen_->EmitKeyedLoad(is_global);
6650 cgen_->frame()->Push(&value); 6658 cgen_->frame()->Push(&value);
6659 if (!persist_after_get_) {
6660 cgen_->UnloadReference(this);
6661 }
6651 break; 6662 break;
6652 } 6663 }
6653 6664
6654 default: 6665 default:
6655 UNREACHABLE(); 6666 UNREACHABLE();
6656 } 6667 }
6657
6658 if (!persist_after_get_) {
6659 cgen_->UnloadReference(this);
6660 }
6661 } 6668 }
6662 6669
6663 6670
6664 void Reference::TakeValue() { 6671 void Reference::TakeValue() {
6665 // For non-constant frame-allocated slots, we invalidate the value in the 6672 // For non-constant frame-allocated slots, we invalidate the value in the
6666 // slot. For all others, we fall back on GetValue. 6673 // slot. For all others, we fall back on GetValue.
6667 ASSERT(!cgen_->in_spilled_code()); 6674 ASSERT(!cgen_->in_spilled_code());
6668 ASSERT(!is_illegal()); 6675 ASSERT(!is_illegal());
6669 if (type_ != SLOT) { 6676 if (type_ != SLOT) {
6670 GetValue(); 6677 GetValue();
(...skipping 3438 matching lines...) Expand 10 before | Expand all | Expand 10 after
10109 10116
10110 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 10117 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
10111 // tagged as a small integer. 10118 // tagged as a small integer.
10112 __ bind(&runtime); 10119 __ bind(&runtime);
10113 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 10120 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
10114 } 10121 }
10115 10122
10116 #undef __ 10123 #undef __
10117 10124
10118 } } // namespace v8::internal 10125 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/full-codegen.cc ('k') | src/ia32/debug-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698