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

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

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 7 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/arm/codegen-arm.h ('k') | src/arm/constants-arm.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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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 #if defined(V8_TARGET_ARCH_ARM)
31
30 #include "bootstrapper.h" 32 #include "bootstrapper.h"
31 #include "codegen-inl.h" 33 #include "codegen-inl.h"
32 #include "compiler.h" 34 #include "compiler.h"
33 #include "debug.h" 35 #include "debug.h"
34 #include "ic-inl.h" 36 #include "ic-inl.h"
35 #include "jsregexp.h" 37 #include "jsregexp.h"
36 #include "jump-target-light-inl.h" 38 #include "jump-target-light-inl.h"
37 #include "parser.h" 39 #include "parser.h"
38 #include "regexp-macro-assembler.h" 40 #include "regexp-macro-assembler.h"
39 #include "regexp-stack.h" 41 #include "regexp-stack.h"
(...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 // and y the receiver. 1363 // and y the receiver.
1362 VirtualFrame::SpilledScope spilled_scope(frame_); 1364 VirtualFrame::SpilledScope spilled_scope(frame_);
1363 1365
1364 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); 1366 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION);
1365 ASSERT(arguments->IsArguments()); 1367 ASSERT(arguments->IsArguments());
1366 1368
1367 // Load applicand.apply onto the stack. This will usually 1369 // Load applicand.apply onto the stack. This will usually
1368 // give us a megamorphic load site. Not super, but it works. 1370 // give us a megamorphic load site. Not super, but it works.
1369 LoadAndSpill(applicand); 1371 LoadAndSpill(applicand);
1370 Handle<String> name = Factory::LookupAsciiSymbol("apply"); 1372 Handle<String> name = Factory::LookupAsciiSymbol("apply");
1373 frame_->Dup();
1371 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET); 1374 frame_->CallLoadIC(name, RelocInfo::CODE_TARGET);
1372 frame_->EmitPush(r0); 1375 frame_->EmitPush(r0);
1373 1376
1374 // Load the receiver and the existing arguments object onto the 1377 // Load the receiver and the existing arguments object onto the
1375 // expression stack. Avoid allocating the arguments object here. 1378 // expression stack. Avoid allocating the arguments object here.
1376 LoadAndSpill(receiver); 1379 LoadAndSpill(receiver);
1377 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF); 1380 LoadFromSlot(scope()->arguments()->var()->slot(), NOT_INSIDE_TYPEOF);
1378 1381
1379 // Emit the source position information after having loaded the 1382 // Emit the source position information after having loaded the
1380 // receiver and the arguments. 1383 // receiver and the arguments.
(...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after
3000 __ bind(&fast); 3003 __ bind(&fast);
3001 } 3004 }
3002 3005
3003 // Load the global object. 3006 // Load the global object.
3004 LoadGlobal(); 3007 LoadGlobal();
3005 // Setup the name register and call load IC. 3008 // Setup the name register and call load IC.
3006 frame_->CallLoadIC(slot->var()->name(), 3009 frame_->CallLoadIC(slot->var()->name(),
3007 typeof_state == INSIDE_TYPEOF 3010 typeof_state == INSIDE_TYPEOF
3008 ? RelocInfo::CODE_TARGET 3011 ? RelocInfo::CODE_TARGET
3009 : RelocInfo::CODE_TARGET_CONTEXT); 3012 : RelocInfo::CODE_TARGET_CONTEXT);
3010 // Drop the global object. The result is in r0.
3011 frame_->Drop();
3012 } 3013 }
3013 3014
3014 3015
3015 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, 3016 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot,
3016 TypeofState typeof_state, 3017 TypeofState typeof_state,
3017 JumpTarget* slow, 3018 JumpTarget* slow,
3018 JumpTarget* done) { 3019 JumpTarget* done) {
3019 // Generate fast-case code for variables that might be shadowed by 3020 // Generate fast-case code for variables that might be shadowed by
3020 // eval-introduced variables. Eval is used a lot without 3021 // eval-introduced variables. Eval is used a lot without
3021 // 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
3415 // 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
3416 // between the current property value and the actual right-hand side. 3417 // between the current property value and the actual right-hand side.
3417 if (is_trivial_receiver) { 3418 if (is_trivial_receiver) {
3418 Load(prop->obj()); 3419 Load(prop->obj());
3419 } else if (var != NULL) { 3420 } else if (var != NULL) {
3420 LoadGlobal(); 3421 LoadGlobal();
3421 } else { 3422 } else {
3422 frame_->Dup(); 3423 frame_->Dup();
3423 } 3424 }
3424 EmitNamedLoad(name, var != NULL); 3425 EmitNamedLoad(name, var != NULL);
3425 frame_->Drop(); // Receiver is left on the stack.
3426 frame_->EmitPush(r0); 3426 frame_->EmitPush(r0);
3427 3427
3428 // Perform the binary operation. 3428 // Perform the binary operation.
3429 Literal* literal = node->value()->AsLiteral(); 3429 Literal* literal = node->value()->AsLiteral();
3430 bool overwrite_value = 3430 bool overwrite_value =
3431 (node->value()->AsBinaryOperation() != NULL && 3431 (node->value()->AsBinaryOperation() != NULL &&
3432 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); 3432 node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
3433 if (literal != NULL && literal->handle()->IsSmi()) { 3433 if (literal != NULL && literal->handle()->IsSmi()) {
3434 SmiOperation(node->binary_op(), 3434 SmiOperation(node->binary_op(),
3435 literal->handle(), 3435 literal->handle(),
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3554 3554
3555 // Stack layout: 3555 // Stack layout:
3556 // [tos] : value 3556 // [tos] : value
3557 // [tos+1] : key 3557 // [tos+1] : key
3558 // [tos+2] : receiver 3558 // [tos+2] : receiver
3559 // [tos+3] : receiver if at the end of an initialization block 3559 // [tos+3] : receiver if at the end of an initialization block
3560 3560
3561 // Perform the assignment. It is safe to ignore constants here. 3561 // Perform the assignment. It is safe to ignore constants here.
3562 ASSERT(node->op() != Token::INIT_CONST); 3562 ASSERT(node->op() != Token::INIT_CONST);
3563 CodeForSourcePosition(node->position()); 3563 CodeForSourcePosition(node->position());
3564 frame_->PopToR0();
3565 EmitKeyedStore(prop->key()->type()); 3564 EmitKeyedStore(prop->key()->type());
3566 frame_->Drop(2); // Key and receiver are left on the stack.
3567 frame_->EmitPush(r0); 3565 frame_->EmitPush(r0);
3568 3566
3569 // Stack layout: 3567 // Stack layout:
3570 // [tos] : result 3568 // [tos] : result
3571 // [tos+1] : receiver if at the end of an initialization block 3569 // [tos+1] : receiver if at the end of an initialization block
3572 3570
3573 // Change to fast case at the end of an initialization block. 3571 // Change to fast case at the end of an initialization block.
3574 if (node->ends_initialization_block()) { 3572 if (node->ends_initialization_block()) {
3575 // The argument to the runtime call is the extra copy of the receiver, 3573 // The argument to the runtime call is the extra copy of the receiver,
3576 // which is below the value of the assignment. Swap the receiver and 3574 // which is below the value of the assignment. Swap the receiver and
(...skipping 1846 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
5510 // Block the constant pool for one more instruction after leaving this 5512 // Block the constant pool for one more instruction after leaving this
5511 // constant pool block scope to include the branch instruction ending the 5513 // constant pool block scope to include the branch instruction ending the
5512 // deferred code. 5514 // deferred code.
5513 __ BlockConstPoolFor(1); 5515 __ BlockConstPoolFor(1);
5514 } 5516 }
5515 } 5517 }
5516 5518
5517 5519
5518 class DeferredReferenceSetKeyedValue: public DeferredCode { 5520 class DeferredReferenceSetKeyedValue: public DeferredCode {
5519 public: 5521 public:
5520 DeferredReferenceSetKeyedValue() { 5522 DeferredReferenceSetKeyedValue(Register value,
5523 Register key,
5524 Register receiver)
5525 : value_(value), key_(key), receiver_(receiver) {
5521 set_comment("[ DeferredReferenceSetKeyedValue"); 5526 set_comment("[ DeferredReferenceSetKeyedValue");
5522 } 5527 }
5523 5528
5524 virtual void Generate(); 5529 virtual void Generate();
5530
5531 private:
5532 Register value_;
5533 Register key_;
5534 Register receiver_;
5525 }; 5535 };
5526 5536
5527 5537
5528 void DeferredReferenceSetKeyedValue::Generate() { 5538 void DeferredReferenceSetKeyedValue::Generate() {
5529 Register scratch1 = VirtualFrame::scratch0(); 5539 Register scratch1 = VirtualFrame::scratch0();
5530 Register scratch2 = VirtualFrame::scratch1(); 5540 Register scratch2 = VirtualFrame::scratch1();
5531 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); 5541 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2);
5532 __ IncrementCounter( 5542 __ IncrementCounter(
5533 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); 5543 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2);
5534 5544
5545 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic
5546 // calling convention.
5547 if (value_.is(r1)) {
5548 __ Swap(r0, r1, ip);
5549 }
5550 ASSERT(receiver_.is(r2));
5551
5535 // The rest of the instructions in the deferred code must be together. 5552 // The rest of the instructions in the deferred code must be together.
5536 { Assembler::BlockConstPoolScope block_const_pool(masm_); 5553 { Assembler::BlockConstPoolScope block_const_pool(masm_);
5537 // Call keyed load IC. It has receiver amd key on the stack and the value to 5554 // Call keyed store IC. It has the arguments value, key and receiver in r0,
5538 // store in r0. 5555 // r1 and r2.
5539 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 5556 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
5540 __ Call(ic, RelocInfo::CODE_TARGET); 5557 __ Call(ic, RelocInfo::CODE_TARGET);
5541 // The call must be followed by a nop instruction to indicate that the 5558 // The call must be followed by a nop instruction to indicate that the
5542 // keyed store has been inlined. 5559 // keyed store has been inlined.
5543 __ nop(PROPERTY_ACCESS_INLINED); 5560 __ nop(PROPERTY_ACCESS_INLINED);
5544 5561
5545 // Block the constant pool for one more instruction after leaving this 5562 // Block the constant pool for one more instruction after leaving this
5546 // constant pool block scope to include the branch instruction ending the 5563 // constant pool block scope to include the branch instruction ending the
5547 // deferred code. 5564 // deferred code.
5548 __ BlockConstPoolFor(1); 5565 __ BlockConstPoolFor(1);
(...skipping 17 matching lines...) Expand all
5566 // having it in the instruction stream below where patching will occur. 5583 // having it in the instruction stream below where patching will occur.
5567 __ IncrementCounter(&Counters::named_load_inline, 1, 5584 __ IncrementCounter(&Counters::named_load_inline, 1,
5568 frame_->scratch0(), frame_->scratch1()); 5585 frame_->scratch0(), frame_->scratch1());
5569 5586
5570 // 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.
5571 // 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
5572 // to be fixed. Therefore the instruction pool is blocked when generating 5589 // to be fixed. Therefore the instruction pool is blocked when generating
5573 // this code 5590 // this code
5574 5591
5575 // Load the receiver from the stack. 5592 // Load the receiver from the stack.
5576 frame_->SpillAllButCopyTOSToR0(); 5593 Register receiver = frame_->PopToRegister();
5594 VirtualFrame::SpilledScope spilled(frame_);
5577 5595
5578 DeferredReferenceGetNamedValue* deferred = 5596 DeferredReferenceGetNamedValue* deferred =
5579 new DeferredReferenceGetNamedValue(name); 5597 new DeferredReferenceGetNamedValue(receiver, name);
5580 5598
5581 #ifdef DEBUG 5599 #ifdef DEBUG
5582 int kInlinedNamedLoadInstructions = 7; 5600 int kInlinedNamedLoadInstructions = 7;
5583 Label check_inlined_codesize; 5601 Label check_inlined_codesize;
5584 masm_->bind(&check_inlined_codesize); 5602 masm_->bind(&check_inlined_codesize);
5585 #endif 5603 #endif
5586 5604
5587 { Assembler::BlockConstPoolScope block_const_pool(masm_); 5605 { Assembler::BlockConstPoolScope block_const_pool(masm_);
5588 // Check that the receiver is a heap object. 5606 // Check that the receiver is a heap object.
5589 __ tst(r0, Operand(kSmiTagMask)); 5607 __ tst(receiver, Operand(kSmiTagMask));
5590 deferred->Branch(eq); 5608 deferred->Branch(eq);
5591 5609
5592 // 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
5593 // code. 5611 // code.
5594 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 5612 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
5595 __ mov(r3, Operand(Factory::null_value())); 5613 __ mov(r3, Operand(Factory::null_value()));
5596 __ cmp(r2, r3); 5614 __ cmp(r2, r3);
5597 deferred->Branch(ne); 5615 deferred->Branch(ne);
5598 5616
5599 // 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
5600 // inline cache code. 5618 // inline cache code.
5601 __ ldr(r0, MemOperand(r0, 0)); 5619 __ ldr(r0, MemOperand(receiver, 0));
5602 5620
5603 // Make sure that the expected number of instructions are generated. 5621 // Make sure that the expected number of instructions are generated.
5604 ASSERT_EQ(kInlinedNamedLoadInstructions, 5622 ASSERT_EQ(kInlinedNamedLoadInstructions,
5605 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 5623 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
5606 } 5624 }
5607 5625
5608 deferred->BindExit(); 5626 deferred->BindExit();
5609 } 5627 }
5610 } 5628 }
5611 5629
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5688 scratch1, 5706 scratch1,
5689 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 5707 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
5690 __ ldr(scratch1, 5708 __ ldr(scratch1,
5691 MemOperand(scratch1, key, LSL, 5709 MemOperand(scratch1, key, LSL,
5692 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize))); 5710 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
5693 __ cmp(scratch1, scratch2); 5711 __ cmp(scratch1, scratch2);
5694 deferred->Branch(eq); 5712 deferred->Branch(eq);
5695 5713
5696 __ mov(r0, scratch1); 5714 __ mov(r0, scratch1);
5697 // Make sure that the expected number of instructions are generated. 5715 // Make sure that the expected number of instructions are generated.
5698 ASSERT_EQ(kInlinedKeyedLoadInstructionsAfterPatchSize, 5716 ASSERT_EQ(kInlinedKeyedLoadInstructionsAfterPatch,
5699 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 5717 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
5700 } 5718 }
5701 5719
5702 deferred->BindExit(); 5720 deferred->BindExit();
5703 } 5721 }
5704 } 5722 }
5705 5723
5706 5724
5707 void CodeGenerator::EmitKeyedStore(StaticType* key_type) { 5725 void CodeGenerator::EmitKeyedStore(StaticType* key_type) {
5708 VirtualFrame::SpilledScope scope(frame_);
5709 // Generate inlined version of the keyed store if the code is in a loop 5726 // Generate inlined version of the keyed store if the code is in a loop
5710 // and the key is likely to be a smi. 5727 // and the key is likely to be a smi.
5711 if (loop_nesting() > 0 && key_type->IsLikelySmi()) { 5728 if (loop_nesting() > 0 && key_type->IsLikelySmi()) {
5712 // Inline the keyed store. 5729 // Inline the keyed store.
5713 Comment cmnt(masm_, "[ Inlined store to keyed property"); 5730 Comment cmnt(masm_, "[ Inlined store to keyed property");
5714 5731
5715 DeferredReferenceSetKeyedValue* deferred = 5732 Register scratch1 = VirtualFrame::scratch0();
5716 new DeferredReferenceSetKeyedValue(); 5733 Register scratch2 = VirtualFrame::scratch1();
5734 Register scratch3 = r3;
5717 5735
5718 // Counter will be decremented in the deferred code. Placed here to avoid 5736 // Counter will be decremented in the deferred code. Placed here to avoid
5719 // having it in the instruction stream below where patching will occur. 5737 // having it in the instruction stream below where patching will occur.
5720 __ IncrementCounter(&Counters::keyed_store_inline, 1, 5738 __ IncrementCounter(&Counters::keyed_store_inline, 1,
5721 frame_->scratch0(), frame_->scratch1()); 5739 scratch1, scratch2);
5740
5741 // Load the value, key and receiver from the stack.
5742 Register value = frame_->PopToRegister();
5743 Register key = frame_->PopToRegister(value);
5744 Register receiver = r2;
5745 frame_->EmitPop(receiver);
5746 VirtualFrame::SpilledScope spilled(frame_);
5747
5748 // The deferred code expects value, key and receiver in registers.
5749 DeferredReferenceSetKeyedValue* deferred =
5750 new DeferredReferenceSetKeyedValue(value, key, receiver);
5722 5751
5723 // Check that the value is a smi. As this inlined code does not set the 5752 // Check that the value is a smi. As this inlined code does not set the
5724 // write barrier it is only possible to store smi values. 5753 // write barrier it is only possible to store smi values.
5725 __ tst(r0, Operand(kSmiTagMask)); 5754 __ tst(value, Operand(kSmiTagMask));
5726 deferred->Branch(ne); 5755 deferred->Branch(ne);
5727 5756
5728 // Load the key and receiver from the stack.
5729 __ ldr(r1, MemOperand(sp, 0));
5730 __ ldr(r2, MemOperand(sp, kPointerSize));
5731
5732 // Check that the key is a smi. 5757 // Check that the key is a smi.
5733 __ tst(r1, Operand(kSmiTagMask)); 5758 __ tst(key, Operand(kSmiTagMask));
5734 deferred->Branch(ne); 5759 deferred->Branch(ne);
5735 5760
5736 // Check that the receiver is a heap object. 5761 // Check that the receiver is a heap object.
5737 __ tst(r2, Operand(kSmiTagMask)); 5762 __ tst(receiver, Operand(kSmiTagMask));
5738 deferred->Branch(eq); 5763 deferred->Branch(eq);
5739 5764
5740 // Check that the receiver is a JSArray. 5765 // Check that the receiver is a JSArray.
5741 __ CompareObjectType(r2, r3, r3, JS_ARRAY_TYPE); 5766 __ CompareObjectType(receiver, scratch1, scratch1, JS_ARRAY_TYPE);
5742 deferred->Branch(ne); 5767 deferred->Branch(ne);
5743 5768
5744 // Check that the key is within bounds. Both the key and the length of 5769 // Check that the key is within bounds. Both the key and the length of
5745 // the JSArray are smis. Use unsigned comparison to handle negative keys. 5770 // the JSArray are smis. Use unsigned comparison to handle negative keys.
5746 __ ldr(r3, FieldMemOperand(r2, JSArray::kLengthOffset)); 5771 __ ldr(scratch1, FieldMemOperand(receiver, JSArray::kLengthOffset));
5747 __ cmp(r3, r1); 5772 __ cmp(scratch1, key);
5748 deferred->Branch(ls); // Unsigned less equal. 5773 deferred->Branch(ls); // Unsigned less equal.
5749 5774
5750 // The following instructions are the part of the inlined store keyed 5775 // The following instructions are the part of the inlined store keyed
5751 // property code which can be patched. Therefore the exact number of 5776 // property code which can be patched. Therefore the exact number of
5752 // instructions generated need to be fixed, so the constant pool is blocked 5777 // instructions generated need to be fixed, so the constant pool is blocked
5753 // while generating this code. 5778 // while generating this code.
5754 #ifdef DEBUG
5755 int kInlinedKeyedStoreInstructions = 7;
5756 Label check_inlined_codesize;
5757 masm_->bind(&check_inlined_codesize);
5758 #endif
5759 { Assembler::BlockConstPoolScope block_const_pool(masm_); 5779 { Assembler::BlockConstPoolScope block_const_pool(masm_);
5760 // Get the elements array from the receiver and check that it 5780 // Get the elements array from the receiver and check that it
5761 // is not a dictionary. 5781 // is not a dictionary.
5762 __ ldr(r3, FieldMemOperand(r2, JSObject::kElementsOffset)); 5782 __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
5763 __ ldr(r4, FieldMemOperand(r3, JSObject::kMapOffset)); 5783 __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset));
5764 // Read the fixed array map from the constant pool (not from the root 5784 // Read the fixed array map from the constant pool (not from the root
5765 // array) so that the value can be patched. When debugging, we patch this 5785 // array) so that the value can be patched. When debugging, we patch this
5766 // comparison to always fail so that we will hit the IC call in the 5786 // comparison to always fail so that we will hit the IC call in the
5767 // deferred code which will allow the debugger to break for fast case 5787 // deferred code which will allow the debugger to break for fast case
5768 // stores. 5788 // stores.
5769 __ mov(r5, Operand(Factory::fixed_array_map())); 5789 #ifdef DEBUG
5770 __ cmp(r4, r5); 5790 Label check_inlined_codesize;
5791 masm_->bind(&check_inlined_codesize);
5792 #endif
5793 __ mov(scratch3, Operand(Factory::fixed_array_map()));
5794 __ cmp(scratch2, scratch3);
5771 deferred->Branch(ne); 5795 deferred->Branch(ne);
5772 5796
5773 // Store the value. 5797 // Store the value.
5774 __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 5798 __ add(scratch1, scratch1,
5775 __ str(r0, MemOperand(r3, r1, LSL, 5799 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
5776 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize))); 5800 __ str(value,
5801 MemOperand(scratch1, key, LSL,
5802 kPointerSizeLog2 - (kSmiTagSize + kSmiShiftSize)));
5777 5803
5778 // Make sure that the expected number of instructions are generated. 5804 // Make sure that the expected number of instructions are generated.
5779 ASSERT_EQ(kInlinedKeyedStoreInstructions, 5805 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch,
5780 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 5806 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
5781 } 5807 }
5782 5808
5783 deferred->BindExit(); 5809 deferred->BindExit();
5784 } else { 5810 } else {
5785 frame()->CallKeyedStoreIC(); 5811 frame()->CallKeyedStoreIC();
5786 } 5812 }
5787 } 5813 }
5788 5814
5789 5815
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
5832 if (!persist_after_get_) { 5858 if (!persist_after_get_) {
5833 cgen_->UnloadReference(this); 5859 cgen_->UnloadReference(this);
5834 } 5860 }
5835 break; 5861 break;
5836 } 5862 }
5837 5863
5838 case NAMED: { 5864 case NAMED: {
5839 Variable* var = expression_->AsVariableProxy()->AsVariable(); 5865 Variable* var = expression_->AsVariableProxy()->AsVariable();
5840 bool is_global = var != NULL; 5866 bool is_global = var != NULL;
5841 ASSERT(!is_global || var->is_global()); 5867 ASSERT(!is_global || var->is_global());
5868 if (persist_after_get_) {
5869 cgen_->frame()->Dup();
5870 }
5842 cgen_->EmitNamedLoad(GetName(), is_global); 5871 cgen_->EmitNamedLoad(GetName(), is_global);
5843 cgen_->frame()->EmitPush(r0); 5872 cgen_->frame()->EmitPush(r0);
5844 if (!persist_after_get_) { 5873 if (!persist_after_get_) set_unloaded();
5845 cgen_->UnloadReference(this);
5846 }
5847 break; 5874 break;
5848 } 5875 }
5849 5876
5850 case KEYED: { 5877 case KEYED: {
5878 ASSERT(property != NULL);
5851 if (persist_after_get_) { 5879 if (persist_after_get_) {
5852 cgen_->frame()->Dup2(); 5880 cgen_->frame()->Dup2();
5853 } 5881 }
5854 ASSERT(property != NULL);
5855 cgen_->EmitKeyedLoad(); 5882 cgen_->EmitKeyedLoad();
5856 cgen_->frame()->EmitPush(r0); 5883 cgen_->frame()->EmitPush(r0);
5857 if (!persist_after_get_) set_unloaded(); 5884 if (!persist_after_get_) set_unloaded();
5858 break; 5885 break;
5859 } 5886 }
5860 5887
5861 default: 5888 default:
5862 UNREACHABLE(); 5889 UNREACHABLE();
5863 } 5890 }
5864 } 5891 }
(...skipping 20 matching lines...) Expand all
5885 5912
5886 case NAMED: { 5913 case NAMED: {
5887 Comment cmnt(masm, "[ Store to named Property"); 5914 Comment cmnt(masm, "[ Store to named Property");
5888 cgen_->EmitNamedStore(GetName(), false); 5915 cgen_->EmitNamedStore(GetName(), false);
5889 frame->EmitPush(r0); 5916 frame->EmitPush(r0);
5890 set_unloaded(); 5917 set_unloaded();
5891 break; 5918 break;
5892 } 5919 }
5893 5920
5894 case KEYED: { 5921 case KEYED: {
5895 VirtualFrame::SpilledScope scope(frame);
5896 Comment cmnt(masm, "[ Store to keyed Property"); 5922 Comment cmnt(masm, "[ Store to keyed Property");
5897 Property* property = expression_->AsProperty(); 5923 Property* property = expression_->AsProperty();
5898 ASSERT(property != NULL); 5924 ASSERT(property != NULL);
5899 cgen_->CodeForSourcePosition(property->position()); 5925 cgen_->CodeForSourcePosition(property->position());
5900
5901 frame->EmitPop(r0); // Value.
5902 cgen_->EmitKeyedStore(property->key()->type()); 5926 cgen_->EmitKeyedStore(property->key()->type());
5903 frame->EmitPush(r0); 5927 frame->EmitPush(r0);
5904 cgen_->UnloadReference(this); 5928 set_unloaded();
5905 break; 5929 break;
5906 } 5930 }
5907 5931
5908 default: 5932 default:
5909 UNREACHABLE(); 5933 UNREACHABLE();
5910 } 5934 }
5911 } 5935 }
5912 5936
5913 5937
5914 void FastNewClosureStub::Generate(MacroAssembler* masm) { 5938 void FastNewClosureStub::Generate(MacroAssembler* masm) {
(...skipping 4098 matching lines...) Expand 10 before | Expand all | Expand 10 after
10013 10037
10014 // Just jump to runtime to add the two strings. 10038 // Just jump to runtime to add the two strings.
10015 __ bind(&string_add_runtime); 10039 __ bind(&string_add_runtime);
10016 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 10040 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
10017 } 10041 }
10018 10042
10019 10043
10020 #undef __ 10044 #undef __
10021 10045
10022 } } // namespace v8::internal 10046 } } // namespace v8::internal
10047
10048 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/constants-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698