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