| 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 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1931 } | 1931 } |
| 1932 node->break_target()->Unuse(); | 1932 node->break_target()->Unuse(); |
| 1933 ASSERT(!has_valid_frame() || frame_->height() == original_height); | 1933 ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| 1934 } | 1934 } |
| 1935 | 1935 |
| 1936 | 1936 |
| 1937 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1937 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 1938 frame_->EmitPush(cp); | 1938 frame_->EmitPush(cp); |
| 1939 frame_->EmitPush(Operand(pairs)); | 1939 frame_->EmitPush(Operand(pairs)); |
| 1940 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 1940 frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 1941 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); |
| 1941 | 1942 |
| 1942 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 1943 frame_->CallRuntime(Runtime::kDeclareGlobals, 4); |
| 1943 // The result is discarded. | 1944 // The result is discarded. |
| 1944 } | 1945 } |
| 1945 | 1946 |
| 1946 | 1947 |
| 1947 void CodeGenerator::VisitDeclaration(Declaration* node) { | 1948 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 1948 #ifdef DEBUG | 1949 #ifdef DEBUG |
| 1949 int original_height = frame_->height(); | 1950 int original_height = frame_->height(); |
| 1950 #endif | 1951 #endif |
| 1951 Comment cmnt(masm_, "[ Declaration"); | 1952 Comment cmnt(masm_, "[ Declaration"); |
| 1952 Variable* var = node->proxy()->var(); | 1953 Variable* var = node->proxy()->var(); |
| (...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3280 // context slot declaration, but we cannot initialize it at the | 3281 // context slot declaration, but we cannot initialize it at the |
| 3281 // same time, because the const declaration may be at the end of | 3282 // same time, because the const declaration may be at the end of |
| 3282 // the eval code (sigh...) and the const variable may have been | 3283 // the eval code (sigh...) and the const variable may have been |
| 3283 // used before (where its value is 'undefined'). Thus, we can only | 3284 // used before (where its value is 'undefined'). Thus, we can only |
| 3284 // do the initialization when we actually encounter the expression | 3285 // do the initialization when we actually encounter the expression |
| 3285 // and when the expression operands are defined and valid, and | 3286 // and when the expression operands are defined and valid, and |
| 3286 // thus we need the split into 2 operations: declaration of the | 3287 // thus we need the split into 2 operations: declaration of the |
| 3287 // context slot followed by initialization. | 3288 // context slot followed by initialization. |
| 3288 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 3289 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 3289 } else { | 3290 } else { |
| 3290 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); | 3291 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); |
| 3292 frame_->CallRuntime(Runtime::kStoreContextSlot, 4); |
| 3291 } | 3293 } |
| 3292 // Storing a variable must keep the (new) value on the expression | 3294 // Storing a variable must keep the (new) value on the expression |
| 3293 // stack. This is necessary for compiling assignment expressions. | 3295 // stack. This is necessary for compiling assignment expressions. |
| 3294 frame_->EmitPush(r0); | 3296 frame_->EmitPush(r0); |
| 3295 | 3297 |
| 3296 } else { | 3298 } else { |
| 3297 ASSERT(!slot->var()->is_dynamic()); | 3299 ASSERT(!slot->var()->is_dynamic()); |
| 3298 Register scratch = VirtualFrame::scratch0(); | 3300 Register scratch = VirtualFrame::scratch0(); |
| 3299 Register scratch2 = VirtualFrame::scratch1(); | 3301 Register scratch2 = VirtualFrame::scratch1(); |
| 3300 | 3302 |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3630 frame_->Drop(); | 3632 frame_->Drop(); |
| 3631 } | 3633 } |
| 3632 break; | 3634 break; |
| 3633 } | 3635 } |
| 3634 // else fall through | 3636 // else fall through |
| 3635 case ObjectLiteral::Property::PROTOTYPE: { | 3637 case ObjectLiteral::Property::PROTOTYPE: { |
| 3636 frame_->Dup(); | 3638 frame_->Dup(); |
| 3637 Load(key); | 3639 Load(key); |
| 3638 Load(value); | 3640 Load(value); |
| 3639 if (property->emit_store()) { | 3641 if (property->emit_store()) { |
| 3640 frame_->CallRuntime(Runtime::kSetProperty, 3); | 3642 frame_->EmitPush(Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 3643 frame_->CallRuntime(Runtime::kSetProperty, 4); |
| 3641 } else { | 3644 } else { |
| 3642 frame_->Drop(3); | 3645 frame_->Drop(3); |
| 3643 } | 3646 } |
| 3644 break; | 3647 break; |
| 3645 } | 3648 } |
| 3646 case ObjectLiteral::Property::SETTER: { | 3649 case ObjectLiteral::Property::SETTER: { |
| 3647 frame_->Dup(); | 3650 frame_->Dup(); |
| 3648 Load(key); | 3651 Load(key); |
| 3649 frame_->EmitPush(Operand(Smi::FromInt(1))); | 3652 frame_->EmitPush(Operand(Smi::FromInt(1))); |
| 3650 Load(value); | 3653 Load(value); |
| (...skipping 3016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6667 // deferred code. | 6670 // deferred code. |
| 6668 __ BlockConstPoolFor(1); | 6671 __ BlockConstPoolFor(1); |
| 6669 } | 6672 } |
| 6670 } | 6673 } |
| 6671 | 6674 |
| 6672 | 6675 |
| 6673 class DeferredReferenceSetKeyedValue: public DeferredCode { | 6676 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 6674 public: | 6677 public: |
| 6675 DeferredReferenceSetKeyedValue(Register value, | 6678 DeferredReferenceSetKeyedValue(Register value, |
| 6676 Register key, | 6679 Register key, |
| 6677 Register receiver) | 6680 Register receiver, |
| 6678 : value_(value), key_(key), receiver_(receiver) { | 6681 StrictModeFlag strict) |
| 6682 : value_(value), key_(key), receiver_(receiver), strict_(strict) { |
| 6679 set_comment("[ DeferredReferenceSetKeyedValue"); | 6683 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 6680 } | 6684 } |
| 6681 | 6685 |
| 6682 virtual void Generate(); | 6686 virtual void Generate(); |
| 6683 | 6687 |
| 6684 private: | 6688 private: |
| 6685 Register value_; | 6689 Register value_; |
| 6686 Register key_; | 6690 Register key_; |
| 6687 Register receiver_; | 6691 Register receiver_; |
| 6692 StrictModeFlag strict_; |
| 6688 }; | 6693 }; |
| 6689 | 6694 |
| 6690 | 6695 |
| 6691 void DeferredReferenceSetKeyedValue::Generate() { | 6696 void DeferredReferenceSetKeyedValue::Generate() { |
| 6692 Register scratch1 = VirtualFrame::scratch0(); | 6697 Register scratch1 = VirtualFrame::scratch0(); |
| 6693 Register scratch2 = VirtualFrame::scratch1(); | 6698 Register scratch2 = VirtualFrame::scratch1(); |
| 6694 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); | 6699 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); |
| 6695 __ IncrementCounter( | 6700 __ IncrementCounter( |
| 6696 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); | 6701 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); |
| 6697 | 6702 |
| 6698 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic | 6703 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic |
| 6699 // calling convention. | 6704 // calling convention. |
| 6700 if (value_.is(r1)) { | 6705 if (value_.is(r1)) { |
| 6701 __ Swap(r0, r1, ip); | 6706 __ Swap(r0, r1, ip); |
| 6702 } | 6707 } |
| 6703 ASSERT(receiver_.is(r2)); | 6708 ASSERT(receiver_.is(r2)); |
| 6704 | 6709 |
| 6705 // The rest of the instructions in the deferred code must be together. | 6710 // The rest of the instructions in the deferred code must be together. |
| 6706 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6711 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| 6707 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6712 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
| 6708 // r1 and r2. | 6713 // r1 and r2. |
| 6709 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 6714 Handle<Code> ic(Builtins::builtin( |
| 6715 strict_ == kStrictMode ? Builtins::KeyedStoreIC_Initialize_Strict |
| 6716 : Builtins::KeyedStoreIC_Initialize)); |
| 6710 __ Call(ic, RelocInfo::CODE_TARGET); | 6717 __ Call(ic, RelocInfo::CODE_TARGET); |
| 6711 // The call must be followed by a nop instruction to indicate that the | 6718 // The call must be followed by a nop instruction to indicate that the |
| 6712 // keyed store has been inlined. | 6719 // keyed store has been inlined. |
| 6713 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6720 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
| 6714 | 6721 |
| 6715 // Block the constant pool for one more instruction after leaving this | 6722 // Block the constant pool for one more instruction after leaving this |
| 6716 // constant pool block scope to include the branch instruction ending the | 6723 // constant pool block scope to include the branch instruction ending the |
| 6717 // deferred code. | 6724 // deferred code. |
| 6718 __ BlockConstPoolFor(1); | 6725 __ BlockConstPoolFor(1); |
| 6719 } | 6726 } |
| 6720 } | 6727 } |
| 6721 | 6728 |
| 6722 | 6729 |
| 6723 class DeferredReferenceSetNamedValue: public DeferredCode { | 6730 class DeferredReferenceSetNamedValue: public DeferredCode { |
| 6724 public: | 6731 public: |
| 6725 DeferredReferenceSetNamedValue(Register value, | 6732 DeferredReferenceSetNamedValue(Register value, |
| 6726 Register receiver, | 6733 Register receiver, |
| 6727 Handle<String> name) | 6734 Handle<String> name, |
| 6728 : value_(value), receiver_(receiver), name_(name) { | 6735 StrictModeFlag strict) |
| 6736 : value_(value), receiver_(receiver), name_(name), strict_(strict) { |
| 6729 set_comment("[ DeferredReferenceSetNamedValue"); | 6737 set_comment("[ DeferredReferenceSetNamedValue"); |
| 6730 } | 6738 } |
| 6731 | 6739 |
| 6732 virtual void Generate(); | 6740 virtual void Generate(); |
| 6733 | 6741 |
| 6734 private: | 6742 private: |
| 6735 Register value_; | 6743 Register value_; |
| 6736 Register receiver_; | 6744 Register receiver_; |
| 6737 Handle<String> name_; | 6745 Handle<String> name_; |
| 6746 StrictModeFlag strict_; |
| 6738 }; | 6747 }; |
| 6739 | 6748 |
| 6740 | 6749 |
| 6741 // Takes value in r0, receiver in r1 and returns the result (the | 6750 // Takes value in r0, receiver in r1 and returns the result (the |
| 6742 // value) in r0. | 6751 // value) in r0. |
| 6743 void DeferredReferenceSetNamedValue::Generate() { | 6752 void DeferredReferenceSetNamedValue::Generate() { |
| 6744 // Record the entry frame and spill. | 6753 // Record the entry frame and spill. |
| 6745 VirtualFrame copied_frame(*frame_state()->frame()); | 6754 VirtualFrame copied_frame(*frame_state()->frame()); |
| 6746 copied_frame.SpillAll(); | 6755 copied_frame.SpillAll(); |
| 6747 | 6756 |
| 6748 // Ensure value in r0, receiver in r1 to match store ic calling | 6757 // Ensure value in r0, receiver in r1 to match store ic calling |
| 6749 // convention. | 6758 // convention. |
| 6750 ASSERT(value_.is(r0) && receiver_.is(r1)); | 6759 ASSERT(value_.is(r0) && receiver_.is(r1)); |
| 6751 __ mov(r2, Operand(name_)); | 6760 __ mov(r2, Operand(name_)); |
| 6752 | 6761 |
| 6753 // The rest of the instructions in the deferred code must be together. | 6762 // The rest of the instructions in the deferred code must be together. |
| 6754 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6763 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| 6755 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6764 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
| 6756 // r1 and r2. | 6765 // r1 and r2. |
| 6757 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 6766 Handle<Code> ic(Builtins::builtin( |
| 6767 strict_ == kStrictMode ? Builtins::StoreIC_Initialize_Strict |
| 6768 : Builtins::StoreIC_Initialize)); |
| 6758 __ Call(ic, RelocInfo::CODE_TARGET); | 6769 __ Call(ic, RelocInfo::CODE_TARGET); |
| 6759 // The call must be followed by a nop instruction to indicate that the | 6770 // The call must be followed by a nop instruction to indicate that the |
| 6760 // named store has been inlined. | 6771 // named store has been inlined. |
| 6761 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6772 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
| 6762 | 6773 |
| 6763 // Go back to the frame we entered with. The instructions | 6774 // Go back to the frame we entered with. The instructions |
| 6764 // generated by this merge are skipped over by the inline store | 6775 // generated by this merge are skipped over by the inline store |
| 6765 // patching mechanism when looking for the branch instruction that | 6776 // patching mechanism when looking for the branch instruction that |
| 6766 // tells it where the code to patch is. | 6777 // tells it where the code to patch is. |
| 6767 copied_frame.MergeTo(frame_state()->frame()); | 6778 copied_frame.MergeTo(frame_state()->frame()); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6936 // Inline the in-object property case. | 6947 // Inline the in-object property case. |
| 6937 JumpTarget slow, done; | 6948 JumpTarget slow, done; |
| 6938 | 6949 |
| 6939 // Get the value and receiver from the stack. | 6950 // Get the value and receiver from the stack. |
| 6940 frame()->PopToR0(); | 6951 frame()->PopToR0(); |
| 6941 Register value = r0; | 6952 Register value = r0; |
| 6942 frame()->PopToR1(); | 6953 frame()->PopToR1(); |
| 6943 Register receiver = r1; | 6954 Register receiver = r1; |
| 6944 | 6955 |
| 6945 DeferredReferenceSetNamedValue* deferred = | 6956 DeferredReferenceSetNamedValue* deferred = |
| 6946 new DeferredReferenceSetNamedValue(value, receiver, name); | 6957 new DeferredReferenceSetNamedValue( |
| 6958 value, receiver, name, strict_mode_flag()); |
| 6947 | 6959 |
| 6948 // Check that the receiver is a heap object. | 6960 // Check that the receiver is a heap object. |
| 6949 __ tst(receiver, Operand(kSmiTagMask)); | 6961 __ tst(receiver, Operand(kSmiTagMask)); |
| 6950 deferred->Branch(eq); | 6962 deferred->Branch(eq); |
| 6951 | 6963 |
| 6952 // The following instructions are the part of the inlined | 6964 // The following instructions are the part of the inlined |
| 6953 // in-object property store code which can be patched. Therefore | 6965 // in-object property store code which can be patched. Therefore |
| 6954 // the exact number of instructions generated must be fixed, so | 6966 // the exact number of instructions generated must be fixed, so |
| 6955 // the constant pool is blocked while generating this code. | 6967 // the constant pool is blocked while generating this code. |
| 6956 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6968 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7122 VirtualFrame::SpilledScope spilled(frame_); | 7134 VirtualFrame::SpilledScope spilled(frame_); |
| 7123 Register receiver = r2; | 7135 Register receiver = r2; |
| 7124 frame_->EmitPop(receiver); | 7136 frame_->EmitPop(receiver); |
| 7125 | 7137 |
| 7126 #ifdef DEBUG | 7138 #ifdef DEBUG |
| 7127 bool we_remembered_the_write_barrier = value_is_harmless; | 7139 bool we_remembered_the_write_barrier = value_is_harmless; |
| 7128 #endif | 7140 #endif |
| 7129 | 7141 |
| 7130 // The deferred code expects value, key and receiver in registers. | 7142 // The deferred code expects value, key and receiver in registers. |
| 7131 DeferredReferenceSetKeyedValue* deferred = | 7143 DeferredReferenceSetKeyedValue* deferred = |
| 7132 new DeferredReferenceSetKeyedValue(value, key, receiver); | 7144 new DeferredReferenceSetKeyedValue( |
| 7145 value, key, receiver, strict_mode_flag()); |
| 7133 | 7146 |
| 7134 // Check that the value is a smi. As this inlined code does not set the | 7147 // Check that the value is a smi. As this inlined code does not set the |
| 7135 // write barrier it is only possible to store smi values. | 7148 // write barrier it is only possible to store smi values. |
| 7136 if (!value_is_harmless) { | 7149 if (!value_is_harmless) { |
| 7137 // If the value is not likely to be a Smi then let's test the fixed array | 7150 // If the value is not likely to be a Smi then let's test the fixed array |
| 7138 // for new space instead. See below. | 7151 // for new space instead. See below. |
| 7139 if (wb_info == LIKELY_SMI) { | 7152 if (wb_info == LIKELY_SMI) { |
| 7140 __ tst(value, Operand(kSmiTagMask)); | 7153 __ tst(value, Operand(kSmiTagMask)); |
| 7141 deferred->Branch(ne); | 7154 deferred->Branch(ne); |
| 7142 #ifdef DEBUG | 7155 #ifdef DEBUG |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7207 | 7220 |
| 7208 // Make sure that the expected number of instructions are generated. | 7221 // Make sure that the expected number of instructions are generated. |
| 7209 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, | 7222 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, |
| 7210 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); | 7223 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
| 7211 } | 7224 } |
| 7212 | 7225 |
| 7213 ASSERT(we_remembered_the_write_barrier); | 7226 ASSERT(we_remembered_the_write_barrier); |
| 7214 | 7227 |
| 7215 deferred->BindExit(); | 7228 deferred->BindExit(); |
| 7216 } else { | 7229 } else { |
| 7217 frame()->CallKeyedStoreIC(); | 7230 frame()->CallKeyedStoreIC(strict_mode_flag()); |
| 7218 } | 7231 } |
| 7219 } | 7232 } |
| 7220 | 7233 |
| 7221 | 7234 |
| 7222 #ifdef DEBUG | 7235 #ifdef DEBUG |
| 7223 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 7236 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
| 7224 #endif | 7237 #endif |
| 7225 | 7238 |
| 7226 | 7239 |
| 7227 #undef __ | 7240 #undef __ |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7375 BinaryOpIC::GetName(runtime_operands_type_)); | 7388 BinaryOpIC::GetName(runtime_operands_type_)); |
| 7376 return name_; | 7389 return name_; |
| 7377 } | 7390 } |
| 7378 | 7391 |
| 7379 | 7392 |
| 7380 #undef __ | 7393 #undef __ |
| 7381 | 7394 |
| 7382 } } // namespace v8::internal | 7395 } } // namespace v8::internal |
| 7383 | 7396 |
| 7384 #endif // V8_TARGET_ARCH_ARM | 7397 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |