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 1352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 // and y the receiver. | 1363 // and y the receiver. |
1364 VirtualFrame::SpilledScope spilled_scope(frame_); | 1364 VirtualFrame::SpilledScope spilled_scope(frame_); |
1365 | 1365 |
1366 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); | 1366 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); |
1367 ASSERT(arguments->IsArguments()); | 1367 ASSERT(arguments->IsArguments()); |
1368 | 1368 |
1369 // Load applicand.apply onto the stack. This will usually | 1369 // Load applicand.apply onto the stack. This will usually |
1370 // give us a megamorphic load site. Not super, but it works. | 1370 // give us a megamorphic load site. Not super, but it works. |
1371 LoadAndSpill(applicand); | 1371 LoadAndSpill(applicand); |
1372 Handle<String> name = Factory::LookupAsciiSymbol("apply"); | 1372 Handle<String> name = Factory::LookupAsciiSymbol("apply"); |
| 1373 frame_->Dup(); |
1373 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); | 1374 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); |
1374 frame_->EmitPush(r0); | 1375 frame_->EmitPush(r0); |
1375 | 1376 |
1376 // Load the receiver and the existing arguments object onto the | 1377 // Load the receiver and the existing arguments object onto the |
1377 // expression stack. Avoid allocating the arguments object here. | 1378 // expression stack. Avoid allocating the arguments object here. |
1378 LoadAndSpill(receiver); | 1379 LoadAndSpill(receiver); |
1379 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); | 1380 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); |
1380 | 1381 |
1381 // Emit the source position information after having loaded the | 1382 // Emit the source position information after having loaded the |
1382 // receiver and the arguments. | 1383 // receiver and the arguments. |
(...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3002 __ bind(&fast); | 3003 __ bind(&fast); |
3003 } | 3004 } |
3004 | 3005 |
3005 // Load the global object. | 3006 // Load the global object. |
3006 LoadGlobal(); | 3007 LoadGlobal(); |
3007 // Setup the name register and call load IC. | 3008 // Setup the name register and call load IC. |
3008 frame_->CallLoadIC(slot->var()->name(), | 3009 frame_->CallLoadIC(slot->var()->name(), |
3009 typeof_state == INSIDE_TYPEOF | 3010 typeof_state == INSIDE_TYPEOF |
3010 ? RelocInfo::CODE_TARGET | 3011 ? RelocInfo::CODE_TARGET |
3011 : RelocInfo::CODE_TARGET_CONTEXT); | 3012 : RelocInfo::CODE_TARGET_CONTEXT); |
3012 // Drop the global object. The result is in r0. | |
3013 frame_->Drop(); | |
3014 } | 3013 } |
3015 | 3014 |
3016 | 3015 |
3017 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, | 3016 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, |
3018 TypeofState typeof_state, | 3017 TypeofState typeof_state, |
3019 JumpTarget* slow, | 3018 JumpTarget* slow, |
3020 JumpTarget* done) { | 3019 JumpTarget* done) { |
3021 // Generate fast-case code for variables that might be shadowed by | 3020 // Generate fast-case code for variables that might be shadowed by |
3022 // eval-introduced variables. Eval is used a lot without | 3021 // eval-introduced variables. Eval is used a lot without |
3023 // introducing variables. In those cases, we do not want to | 3022 // introducing variables. In those cases, we do not want to |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3417 // For a compound assignment the right-hand side is a binary operation | 3416 // For a compound assignment the right-hand side is a binary operation |
3418 // between the current property value and the actual right-hand side. | 3417 // between the current property value and the actual right-hand side. |
3419 if (is_trivial_receiver) { | 3418 if (is_trivial_receiver) { |
3420 Load(prop->obj()); | 3419 Load(prop->obj()); |
3421 } else if (var != NULL) { | 3420 } else if (var != NULL) { |
3422 LoadGlobal(); | 3421 LoadGlobal(); |
3423 } else { | 3422 } else { |
3424 frame_->Dup(); | 3423 frame_->Dup(); |
3425 } | 3424 } |
3426 EmitNamedLoad(name, var != NULL); | 3425 EmitNamedLoad(name, var != NULL); |
3427 frame_->Drop(); // Receiver is left on the stack. | |
3428 frame_->EmitPush(r0); | 3426 frame_->EmitPush(r0); |
3429 | 3427 |
3430 // Perform the binary operation. | 3428 // Perform the binary operation. |
3431 Literal* literal = node->value()->AsLiteral(); | 3429 Literal* literal = node->value()->AsLiteral(); |
3432 bool overwrite_value = | 3430 bool overwrite_value = |
3433 (node->value()->AsBinaryOperation() != NULL && | 3431 (node->value()->AsBinaryOperation() != NULL && |
3434 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 3432 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
3435 if (literal != NULL && literal->handle()->IsSmi()) { | 3433 if (literal != NULL && literal->handle()->IsSmi()) { |
3436 SmiOperation(node->binary_op(), | 3434 SmiOperation(node->binary_op(), |
3437 literal->handle(), | 3435 literal->handle(), |
(...skipping 1985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5423 default: | 5421 default: |
5424 UNREACHABLE(); | 5422 UNREACHABLE(); |
5425 } | 5423 } |
5426 ASSERT((has_cc() && frame_->height() == original_height) || | 5424 ASSERT((has_cc() && frame_->height() == original_height) || |
5427 (!has_cc() && frame_->height() == original_height + 1)); | 5425 (!has_cc() && frame_->height() == original_height + 1)); |
5428 } | 5426 } |
5429 | 5427 |
5430 | 5428 |
5431 class DeferredReferenceGetNamedValue: public DeferredCode { | 5429 class DeferredReferenceGetNamedValue: public DeferredCode { |
5432 public: | 5430 public: |
5433 explicit DeferredReferenceGetNamedValue(Handle<String> name) : name_(name) { | 5431 explicit DeferredReferenceGetNamedValue(Register receiver, |
| 5432 Handle<String> name) |
| 5433 : receiver_(receiver), name_(name) { |
5434 set_comment("[ DeferredReferenceGetNamedValue"); | 5434 set_comment("[ DeferredReferenceGetNamedValue"); |
5435 } | 5435 } |
5436 | 5436 |
5437 virtual void Generate(); | 5437 virtual void Generate(); |
5438 | 5438 |
5439 private: | 5439 private: |
| 5440 Register receiver_; |
5440 Handle<String> name_; | 5441 Handle<String> name_; |
5441 }; | 5442 }; |
5442 | 5443 |
5443 | 5444 |
5444 void DeferredReferenceGetNamedValue::Generate() { | 5445 void DeferredReferenceGetNamedValue::Generate() { |
| 5446 ASSERT(receiver_.is(r0) || receiver_.is(r1)); |
| 5447 |
5445 Register scratch1 = VirtualFrame::scratch0(); | 5448 Register scratch1 = VirtualFrame::scratch0(); |
5446 Register scratch2 = VirtualFrame::scratch1(); | 5449 Register scratch2 = VirtualFrame::scratch1(); |
5447 __ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2); | 5450 __ DecrementCounter(&Counters::named_load_inline, 1, scratch1, scratch2); |
5448 __ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1, scratch2); | 5451 __ IncrementCounter(&Counters::named_load_inline_miss, 1, scratch1, scratch2); |
5449 | 5452 |
5450 // Setup the registers and call load IC. | 5453 // Ensure receiver in r0 and name in r2 to match load ic calling convention. |
5451 // On entry to this deferred code, r0 is assumed to already contain the | 5454 __ Move(r0, receiver_); |
5452 // receiver from the top of the stack. | |
5453 __ mov(r2, Operand(name_)); | 5455 __ mov(r2, Operand(name_)); |
5454 | 5456 |
5455 // The rest of the instructions in the deferred code must be together. | 5457 // The rest of the instructions in the deferred code must be together. |
5456 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 5458 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
5457 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 5459 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
5458 __ Call(ic, RelocInfo::CODE_TARGET); | 5460 __ Call(ic, RelocInfo::CODE_TARGET); |
5459 // The call must be followed by a nop(1) instruction to indicate that the | 5461 // The call must be followed by a nop(1) instruction to indicate that the |
5460 // in-object has been inlined. | 5462 // in-object has been inlined. |
5461 __ nop(PROPERTY_ACCESS_INLINED); | 5463 __ nop(PROPERTY_ACCESS_INLINED); |
5462 | 5464 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5581 // having it in the instruction stream below where patching will occur. | 5583 // having it in the instruction stream below where patching will occur. |
5582 __ IncrementCounter(&Counters::named_load_inline, 1, | 5584 __ IncrementCounter(&Counters::named_load_inline, 1, |
5583 frame_->scratch0(), frame_->scratch1()); | 5585 frame_->scratch0(), frame_->scratch1()); |
5584 | 5586 |
5585 // The following instructions are the inlined load of an in-object property. | 5587 // The following instructions are the inlined load of an in-object property. |
5586 // Parts of this code is patched, so the exact instructions generated needs | 5588 // Parts of this code is patched, so the exact instructions generated needs |
5587 // to be fixed. Therefore the instruction pool is blocked when generating | 5589 // to be fixed. Therefore the instruction pool is blocked when generating |
5588 // this code | 5590 // this code |
5589 | 5591 |
5590 // Load the receiver from the stack. | 5592 // Load the receiver from the stack. |
5591 frame_->SpillAllButCopyTOSToR0(); | 5593 Register receiver = frame_->PopToRegister(); |
| 5594 VirtualFrame::SpilledScope spilled(frame_); |
5592 | 5595 |
5593 DeferredReferenceGetNamedValue* deferred = | 5596 DeferredReferenceGetNamedValue* deferred = |
5594 new DeferredReferenceGetNamedValue(name); | 5597 new DeferredReferenceGetNamedValue(receiver, name); |
5595 | 5598 |
5596 #ifdef DEBUG | 5599 #ifdef DEBUG |
5597 int kInlinedNamedLoadInstructions = 7; | 5600 int kInlinedNamedLoadInstructions = 7; |
5598 Label check_inlined_codesize; | 5601 Label check_inlined_codesize; |
5599 masm_->bind(&check_inlined_codesize); | 5602 masm_->bind(&check_inlined_codesize); |
5600 #endif | 5603 #endif |
5601 | 5604 |
5602 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 5605 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
5603 // Check that the receiver is a heap object. | 5606 // Check that the receiver is a heap object. |
5604 __ tst(r0, Operand(kSmiTagMask)); | 5607 __ tst(receiver, Operand(kSmiTagMask)); |
5605 deferred->Branch(eq); | 5608 deferred->Branch(eq); |
5606 | 5609 |
5607 // Check the map. The null map used below is patched by the inline cache | 5610 // Check the map. The null map used below is patched by the inline cache |
5608 // code. | 5611 // code. |
5609 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5612 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
5610 __ mov(r3, Operand(Factory::null_value())); | 5613 __ mov(r3, Operand(Factory::null_value())); |
5611 __ cmp(r2, r3); | 5614 __ cmp(r2, r3); |
5612 deferred->Branch(ne); | 5615 deferred->Branch(ne); |
5613 | 5616 |
5614 // Initially use an invalid index. The index will be patched by the | 5617 // Initially use an invalid index. The index will be patched by the |
5615 // inline cache code. | 5618 // inline cache code. |
5616 __ ldr(r0, MemOperand(r0, 0)); | 5619 __ ldr(r0, MemOperand(receiver, 0)); |
5617 | 5620 |
5618 // Make sure that the expected number of instructions are generated. | 5621 // Make sure that the expected number of instructions are generated. |
5619 ASSERT_EQ(kInlinedNamedLoadInstructions, | 5622 ASSERT_EQ(kInlinedNamedLoadInstructions, |
5620 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); | 5623 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
5621 } | 5624 } |
5622 | 5625 |
5623 deferred->BindExit(); | 5626 deferred->BindExit(); |
5624 } | 5627 } |
5625 } | 5628 } |
5626 | 5629 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5855 if (!persist_after_get_) { | 5858 if (!persist_after_get_) { |
5856 cgen_->UnloadReference(this); | 5859 cgen_->UnloadReference(this); |
5857 } | 5860 } |
5858 break; | 5861 break; |
5859 } | 5862 } |
5860 | 5863 |
5861 case NAMED: { | 5864 case NAMED: { |
5862 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5865 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
5863 bool is_global = var != NULL; | 5866 bool is_global = var != NULL; |
5864 ASSERT(!is_global || var->is_global()); | 5867 ASSERT(!is_global || var->is_global()); |
| 5868 if (persist_after_get_) { |
| 5869 cgen_->frame()->Dup(); |
| 5870 } |
5865 cgen_->EmitNamedLoad(GetName(), is_global); | 5871 cgen_->EmitNamedLoad(GetName(), is_global); |
5866 cgen_->frame()->EmitPush(r0); | 5872 cgen_->frame()->EmitPush(r0); |
5867 if (!persist_after_get_) { | 5873 if (!persist_after_get_) set_unloaded(); |
5868 cgen_->UnloadReference(this); | |
5869 } | |
5870 break; | 5874 break; |
5871 } | 5875 } |
5872 | 5876 |
5873 case KEYED: { | 5877 case KEYED: { |
| 5878 ASSERT(property != NULL); |
5874 if (persist_after_get_) { | 5879 if (persist_after_get_) { |
5875 cgen_->frame()->Dup2(); | 5880 cgen_->frame()->Dup2(); |
5876 } | 5881 } |
5877 ASSERT(property != NULL); | |
5878 cgen_->EmitKeyedLoad(); | 5882 cgen_->EmitKeyedLoad(); |
5879 cgen_->frame()->EmitPush(r0); | 5883 cgen_->frame()->EmitPush(r0); |
5880 if (!persist_after_get_) set_unloaded(); | 5884 if (!persist_after_get_) set_unloaded(); |
5881 break; | 5885 break; |
5882 } | 5886 } |
5883 | 5887 |
5884 default: | 5888 default: |
5885 UNREACHABLE(); | 5889 UNREACHABLE(); |
5886 } | 5890 } |
5887 } | 5891 } |
(...skipping 4147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10035 __ bind(&string_add_runtime); | 10039 __ bind(&string_add_runtime); |
10036 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10040 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10037 } | 10041 } |
10038 | 10042 |
10039 | 10043 |
10040 #undef __ | 10044 #undef __ |
10041 | 10045 |
10042 } } // namespace v8::internal | 10046 } } // namespace v8::internal |
10043 | 10047 |
10044 #endif // V8_TARGET_ARCH_ARM | 10048 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |