| 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 |