OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |