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 3455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3466 | 3466 |
3467 // Stack layout: | 3467 // Stack layout: |
3468 // [tos] : key | 3468 // [tos] : key |
3469 // [tos+1] : receiver | 3469 // [tos+1] : receiver |
3470 // [tos+2] : receiver if at the end of an initialization block | 3470 // [tos+2] : receiver if at the end of an initialization block |
3471 | 3471 |
3472 // Evaluate the right-hand side. | 3472 // Evaluate the right-hand side. |
3473 if (node->is_compound()) { | 3473 if (node->is_compound()) { |
3474 // For a compound assignment the right-hand side is a binary operation | 3474 // For a compound assignment the right-hand side is a binary operation |
3475 // between the current property value and the actual right-hand side. | 3475 // between the current property value and the actual right-hand side. |
3476 // Load of the current value leaves receiver and key on the stack. | 3476 // Duplicate receiver and key for loading the current property value. |
| 3477 frame_->Dup2(); |
3477 EmitKeyedLoad(); | 3478 EmitKeyedLoad(); |
3478 frame_->EmitPush(r0); | 3479 frame_->EmitPush(r0); |
3479 | 3480 |
3480 // Perform the binary operation. | 3481 // Perform the binary operation. |
3481 Literal* literal = node->value()->AsLiteral(); | 3482 Literal* literal = node->value()->AsLiteral(); |
3482 bool overwrite_value = | 3483 bool overwrite_value = |
3483 (node->value()->AsBinaryOperation() != NULL && | 3484 (node->value()->AsBinaryOperation() != NULL && |
3484 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 3485 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
3485 if (literal != NULL && literal->handle()->IsSmi()) { | 3486 if (literal != NULL && literal->handle()->IsSmi()) { |
3486 SmiOperation(node->binary_op(), | 3487 SmiOperation(node->binary_op(), |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3760 __ ldr(cp, frame_->Context()); | 3761 __ ldr(cp, frame_->Context()); |
3761 frame_->EmitPush(r0); | 3762 frame_->EmitPush(r0); |
3762 } | 3763 } |
3763 | 3764 |
3764 } else { | 3765 } else { |
3765 // ------------------------------------------- | 3766 // ------------------------------------------- |
3766 // JavaScript example: 'array[index](1, 2, 3)' | 3767 // JavaScript example: 'array[index](1, 2, 3)' |
3767 // ------------------------------------------- | 3768 // ------------------------------------------- |
3768 | 3769 |
3769 LoadAndSpill(property->obj()); | 3770 LoadAndSpill(property->obj()); |
| 3771 if (!property->is_synthetic()) { |
| 3772 // Duplicate receiver for later use. |
| 3773 __ ldr(r0, MemOperand(sp, 0)); |
| 3774 frame_->EmitPush(r0); |
| 3775 } |
3770 LoadAndSpill(property->key()); | 3776 LoadAndSpill(property->key()); |
3771 EmitKeyedLoad(); | 3777 EmitKeyedLoad(); |
3772 frame_->Drop(); // key | |
3773 // Put the function below the receiver. | 3778 // Put the function below the receiver. |
3774 if (property->is_synthetic()) { | 3779 if (property->is_synthetic()) { |
3775 // Use the global receiver. | 3780 // Use the global receiver. |
3776 frame_->Drop(); | 3781 frame_->EmitPush(r0); // Function. |
3777 frame_->EmitPush(r0); | |
3778 LoadGlobalReceiver(r0); | 3782 LoadGlobalReceiver(r0); |
3779 } else { | 3783 } else { |
3780 frame_->EmitPop(r1); // receiver | 3784 // Switch receiver and function. |
3781 frame_->EmitPush(r0); // function | 3785 frame_->EmitPop(r1); // Receiver. |
3782 frame_->EmitPush(r1); // receiver | 3786 frame_->EmitPush(r0); // Function. |
| 3787 frame_->EmitPush(r1); // Receiver. |
3783 } | 3788 } |
3784 | 3789 |
3785 // Call the function. | 3790 // Call the function. |
3786 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); | 3791 CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position()); |
3787 frame_->EmitPush(r0); | 3792 frame_->EmitPush(r0); |
3788 } | 3793 } |
3789 | 3794 |
3790 } else { | 3795 } else { |
3791 // ---------------------------------- | 3796 // ---------------------------------- |
3792 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 3797 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
(...skipping 1588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5381 | 5386 |
5382 | 5387 |
5383 void DeferredReferenceGetKeyedValue::Generate() { | 5388 void DeferredReferenceGetKeyedValue::Generate() { |
5384 Register scratch1 = VirtualFrame::scratch0(); | 5389 Register scratch1 = VirtualFrame::scratch0(); |
5385 Register scratch2 = VirtualFrame::scratch1(); | 5390 Register scratch2 = VirtualFrame::scratch1(); |
5386 __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2); | 5391 __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2); |
5387 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2); | 5392 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2); |
5388 | 5393 |
5389 // The rest of the instructions in the deferred code must be together. | 5394 // The rest of the instructions in the deferred code must be together. |
5390 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 5395 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
5391 // Call keyed load IC. It has all arguments on the stack and the key in r0. | 5396 // Call keyed load IC. It has the arguments key and receiver in r0 and r1. |
5392 __ ldr(r0, MemOperand(sp, 0)); | |
5393 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 5397 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
5394 __ Call(ic, RelocInfo::CODE_TARGET); | 5398 __ Call(ic, RelocInfo::CODE_TARGET); |
5395 // The call must be followed by a nop instruction to indicate that the | 5399 // The call must be followed by a nop instruction to indicate that the |
5396 // keyed load has been inlined. | 5400 // keyed load has been inlined. |
5397 __ nop(PROPERTY_ACCESS_INLINED); | 5401 __ nop(PROPERTY_ACCESS_INLINED); |
5398 | 5402 |
5399 // Block the constant pool for one more instruction after leaving this | 5403 // Block the constant pool for one more instruction after leaving this |
5400 // constant pool block scope to include the branch instruction ending the | 5404 // constant pool block scope to include the branch instruction ending the |
5401 // deferred code. | 5405 // deferred code. |
5402 __ BlockConstPoolFor(1); | 5406 __ BlockConstPoolFor(1); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5515 frame_->CallKeyedLoadIC(); | 5519 frame_->CallKeyedLoadIC(); |
5516 } else { | 5520 } else { |
5517 // Inline the keyed load. | 5521 // Inline the keyed load. |
5518 Comment cmnt(masm_, "[ Inlined load from keyed property"); | 5522 Comment cmnt(masm_, "[ Inlined load from keyed property"); |
5519 | 5523 |
5520 // Counter will be decremented in the deferred code. Placed here to avoid | 5524 // Counter will be decremented in the deferred code. Placed here to avoid |
5521 // having it in the instruction stream below where patching will occur. | 5525 // having it in the instruction stream below where patching will occur. |
5522 __ IncrementCounter(&Counters::keyed_load_inline, 1, | 5526 __ IncrementCounter(&Counters::keyed_load_inline, 1, |
5523 frame_->scratch0(), frame_->scratch1()); | 5527 frame_->scratch0(), frame_->scratch1()); |
5524 | 5528 |
5525 // Load the receiver and key from the stack. | 5529 // Load the key and receiver from the stack to r0 and r1. |
5526 frame_->SpillAllButCopyTOSToR1R0(); | 5530 frame_->PopToR1R0(); |
5527 Register receiver = r0; | 5531 Register receiver = r0; |
5528 Register key = r1; | 5532 Register key = r1; |
5529 VirtualFrame::SpilledScope spilled(frame_); | 5533 VirtualFrame::SpilledScope spilled(frame_); |
5530 | 5534 |
| 5535 // The deferred code expects key and receiver in r0 and r1. |
5531 DeferredReferenceGetKeyedValue* deferred = | 5536 DeferredReferenceGetKeyedValue* deferred = |
5532 new DeferredReferenceGetKeyedValue(); | 5537 new DeferredReferenceGetKeyedValue(); |
5533 | 5538 |
5534 // Check that the receiver is a heap object. | 5539 // Check that the receiver is a heap object. |
5535 __ tst(receiver, Operand(kSmiTagMask)); | 5540 __ tst(receiver, Operand(kSmiTagMask)); |
5536 deferred->Branch(eq); | 5541 deferred->Branch(eq); |
5537 | 5542 |
5538 // The following instructions are the part of the inlined load keyed | 5543 // The following instructions are the part of the inlined load keyed |
5539 // property code which can be patched. Therefore the exact number of | 5544 // property code which can be patched. Therefore the exact number of |
5540 // instructions generated need to be fixed, so the constant pool is blocked | 5545 // instructions generated need to be fixed, so the constant pool is blocked |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5714 if (property != NULL) { | 5719 if (property != NULL) { |
5715 cgen_->CodeForSourcePosition(property->position()); | 5720 cgen_->CodeForSourcePosition(property->position()); |
5716 } | 5721 } |
5717 | 5722 |
5718 switch (type_) { | 5723 switch (type_) { |
5719 case SLOT: { | 5724 case SLOT: { |
5720 Comment cmnt(masm, "[ Load from Slot"); | 5725 Comment cmnt(masm, "[ Load from Slot"); |
5721 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 5726 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
5722 ASSERT(slot != NULL); | 5727 ASSERT(slot != NULL); |
5723 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5728 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 5729 if (!persist_after_get_) { |
| 5730 cgen_->UnloadReference(this); |
| 5731 } |
5724 break; | 5732 break; |
5725 } | 5733 } |
5726 | 5734 |
5727 case NAMED: { | 5735 case NAMED: { |
5728 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 5736 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
5729 bool is_global = var != NULL; | 5737 bool is_global = var != NULL; |
5730 ASSERT(!is_global || var->is_global()); | 5738 ASSERT(!is_global || var->is_global()); |
5731 cgen_->EmitNamedLoad(GetName(), is_global); | 5739 cgen_->EmitNamedLoad(GetName(), is_global); |
5732 cgen_->frame()->EmitPush(r0); | 5740 cgen_->frame()->EmitPush(r0); |
| 5741 if (!persist_after_get_) { |
| 5742 cgen_->UnloadReference(this); |
| 5743 } |
5733 break; | 5744 break; |
5734 } | 5745 } |
5735 | 5746 |
5736 case KEYED: { | 5747 case KEYED: { |
| 5748 if (persist_after_get_) { |
| 5749 cgen_->frame()->Dup2(); |
| 5750 } |
5737 ASSERT(property != NULL); | 5751 ASSERT(property != NULL); |
5738 cgen_->EmitKeyedLoad(); | 5752 cgen_->EmitKeyedLoad(); |
5739 cgen_->frame()->EmitPush(r0); | 5753 cgen_->frame()->EmitPush(r0); |
| 5754 if (!persist_after_get_) set_unloaded(); |
5740 break; | 5755 break; |
5741 } | 5756 } |
5742 | 5757 |
5743 default: | 5758 default: |
5744 UNREACHABLE(); | 5759 UNREACHABLE(); |
5745 } | 5760 } |
5746 | |
5747 if (!persist_after_get_) { | |
5748 cgen_->UnloadReference(this); | |
5749 } | |
5750 } | 5761 } |
5751 | 5762 |
5752 | 5763 |
5753 void Reference::SetValue(InitState init_state) { | 5764 void Reference::SetValue(InitState init_state) { |
5754 ASSERT(!is_illegal()); | 5765 ASSERT(!is_illegal()); |
5755 ASSERT(!cgen_->has_cc()); | 5766 ASSERT(!cgen_->has_cc()); |
5756 MacroAssembler* masm = cgen_->masm(); | 5767 MacroAssembler* masm = cgen_->masm(); |
5757 VirtualFrame* frame = cgen_->frame(); | 5768 VirtualFrame* frame = cgen_->frame(); |
5758 Property* property = expression_->AsProperty(); | 5769 Property* property = expression_->AsProperty(); |
5759 if (property != NULL) { | 5770 if (property != NULL) { |
(...skipping 4141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9901 | 9912 |
9902 // Just jump to runtime to add the two strings. | 9913 // Just jump to runtime to add the two strings. |
9903 __ bind(&string_add_runtime); | 9914 __ bind(&string_add_runtime); |
9904 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 9915 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
9905 } | 9916 } |
9906 | 9917 |
9907 | 9918 |
9908 #undef __ | 9919 #undef __ |
9909 | 9920 |
9910 } } // namespace v8::internal | 9921 } } // namespace v8::internal |
OLD | NEW |