| 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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3631 frame_->Drop(); | 3633 frame_->Drop(); |
| 3632 } | 3634 } |
| 3633 break; | 3635 break; |
| 3634 } | 3636 } |
| 3635 // else fall through | 3637 // else fall through |
| 3636 case ObjectLiteral::Property::PROTOTYPE: { | 3638 case ObjectLiteral::Property::PROTOTYPE: { |
| 3637 frame_->Dup(); | 3639 frame_->Dup(); |
| 3638 Load(key); | 3640 Load(key); |
| 3639 Load(value); | 3641 Load(value); |
| 3640 if (property->emit_store()) { | 3642 if (property->emit_store()) { |
| 3641 frame_->CallRuntime(Runtime::kSetProperty, 3); | 3643 frame_->EmitPush(Operand(Smi::FromInt(NONE))); // PropertyAttributes |
| 3644 frame_->CallRuntime(Runtime::kSetProperty, 4); |
| 3642 } else { | 3645 } else { |
| 3643 frame_->Drop(3); | 3646 frame_->Drop(3); |
| 3644 } | 3647 } |
| 3645 break; | 3648 break; |
| 3646 } | 3649 } |
| 3647 case ObjectLiteral::Property::SETTER: { | 3650 case ObjectLiteral::Property::SETTER: { |
| 3648 frame_->Dup(); | 3651 frame_->Dup(); |
| 3649 Load(key); | 3652 Load(key); |
| 3650 frame_->EmitPush(Operand(Smi::FromInt(1))); | 3653 frame_->EmitPush(Operand(Smi::FromInt(1))); |
| 3651 Load(value); | 3654 Load(value); |
| (...skipping 1515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5167 __ ldr(scratch2_, | 5170 __ ldr(scratch2_, |
| 5168 FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset)); | 5171 FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset)); |
| 5169 __ ldr(scratch2_, | 5172 __ ldr(scratch2_, |
| 5170 ContextOperand( | 5173 ContextOperand( |
| 5171 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 5174 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 5172 __ cmp(scratch1_, scratch2_); | 5175 __ cmp(scratch1_, scratch2_); |
| 5173 __ b(ne, &false_result); | 5176 __ b(ne, &false_result); |
| 5174 | 5177 |
| 5175 // Set the bit in the map to indicate that it has been checked safe for | 5178 // Set the bit in the map to indicate that it has been checked safe for |
| 5176 // default valueOf and set true result. | 5179 // default valueOf and set true result. |
| 5177 __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); | 5180 __ ldrb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); |
| 5178 __ orr(scratch1_, | 5181 __ orr(scratch1_, |
| 5179 scratch1_, | 5182 scratch1_, |
| 5180 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 5183 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 5181 __ str(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); | 5184 __ strb(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); |
| 5182 __ mov(map_result_, Operand(1)); | 5185 __ mov(map_result_, Operand(1)); |
| 5183 __ jmp(exit_label()); | 5186 __ jmp(exit_label()); |
| 5184 __ bind(&false_result); | 5187 __ bind(&false_result); |
| 5185 // Set false result. | 5188 // Set false result. |
| 5186 __ mov(map_result_, Operand(0, RelocInfo::NONE)); | 5189 __ mov(map_result_, Operand(0, RelocInfo::NONE)); |
| 5187 } | 5190 } |
| 5188 | 5191 |
| 5189 private: | 5192 private: |
| 5190 Register object_; | 5193 Register object_; |
| 5191 Register map_result_; | 5194 Register map_result_; |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5653 Load(args->at(n_args + 1)); // function | 5656 Load(args->at(n_args + 1)); // function |
| 5654 frame_->CallJSFunction(n_args); | 5657 frame_->CallJSFunction(n_args); |
| 5655 frame_->EmitPush(r0); | 5658 frame_->EmitPush(r0); |
| 5656 } | 5659 } |
| 5657 | 5660 |
| 5658 | 5661 |
| 5659 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 5662 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 5660 ASSERT_EQ(args->length(), 1); | 5663 ASSERT_EQ(args->length(), 1); |
| 5661 Load(args->at(0)); | 5664 Load(args->at(0)); |
| 5662 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 5665 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 5663 TranscendentalCacheStub stub(TranscendentalCache::SIN); | 5666 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 5667 TranscendentalCacheStub::TAGGED); |
| 5664 frame_->SpillAllButCopyTOSToR0(); | 5668 frame_->SpillAllButCopyTOSToR0(); |
| 5665 frame_->CallStub(&stub, 1); | 5669 frame_->CallStub(&stub, 1); |
| 5666 } else { | 5670 } else { |
| 5667 frame_->CallRuntime(Runtime::kMath_sin, 1); | 5671 frame_->CallRuntime(Runtime::kMath_sin, 1); |
| 5668 } | 5672 } |
| 5669 frame_->EmitPush(r0); | 5673 frame_->EmitPush(r0); |
| 5670 } | 5674 } |
| 5671 | 5675 |
| 5672 | 5676 |
| 5673 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 5677 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 5674 ASSERT_EQ(args->length(), 1); | 5678 ASSERT_EQ(args->length(), 1); |
| 5675 Load(args->at(0)); | 5679 Load(args->at(0)); |
| 5676 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 5680 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 5677 TranscendentalCacheStub stub(TranscendentalCache::COS); | 5681 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 5682 TranscendentalCacheStub::TAGGED); |
| 5678 frame_->SpillAllButCopyTOSToR0(); | 5683 frame_->SpillAllButCopyTOSToR0(); |
| 5679 frame_->CallStub(&stub, 1); | 5684 frame_->CallStub(&stub, 1); |
| 5680 } else { | 5685 } else { |
| 5681 frame_->CallRuntime(Runtime::kMath_cos, 1); | 5686 frame_->CallRuntime(Runtime::kMath_cos, 1); |
| 5682 } | 5687 } |
| 5683 frame_->EmitPush(r0); | 5688 frame_->EmitPush(r0); |
| 5684 } | 5689 } |
| 5685 | 5690 |
| 5686 | 5691 |
| 5687 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { | 5692 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { |
| 5688 ASSERT_EQ(args->length(), 1); | 5693 ASSERT_EQ(args->length(), 1); |
| 5689 Load(args->at(0)); | 5694 Load(args->at(0)); |
| 5690 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 5695 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 5691 TranscendentalCacheStub stub(TranscendentalCache::LOG); | 5696 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 5697 TranscendentalCacheStub::TAGGED); |
| 5692 frame_->SpillAllButCopyTOSToR0(); | 5698 frame_->SpillAllButCopyTOSToR0(); |
| 5693 frame_->CallStub(&stub, 1); | 5699 frame_->CallStub(&stub, 1); |
| 5694 } else { | 5700 } else { |
| 5695 frame_->CallRuntime(Runtime::kMath_log, 1); | 5701 frame_->CallRuntime(Runtime::kMath_log, 1); |
| 5696 } | 5702 } |
| 5697 frame_->EmitPush(r0); | 5703 frame_->EmitPush(r0); |
| 5698 } | 5704 } |
| 5699 | 5705 |
| 5700 | 5706 |
| 5701 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 5707 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5842 // LoadCondition may (and usually does) leave a test and branch to | 5848 // LoadCondition may (and usually does) leave a test and branch to |
| 5843 // be emitted by the caller. In that case, negate the condition. | 5849 // be emitted by the caller. In that case, negate the condition. |
| 5844 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 5850 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
| 5845 | 5851 |
| 5846 } else if (op == Token::DELETE) { | 5852 } else if (op == Token::DELETE) { |
| 5847 Property* property = node->expression()->AsProperty(); | 5853 Property* property = node->expression()->AsProperty(); |
| 5848 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); | 5854 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); |
| 5849 if (property != NULL) { | 5855 if (property != NULL) { |
| 5850 Load(property->obj()); | 5856 Load(property->obj()); |
| 5851 Load(property->key()); | 5857 Load(property->key()); |
| 5852 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | 5858 frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag()))); |
| 5859 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3); |
| 5853 frame_->EmitPush(r0); | 5860 frame_->EmitPush(r0); |
| 5854 | 5861 |
| 5855 } else if (variable != NULL) { | 5862 } else if (variable != NULL) { |
| 5863 // Delete of an unqualified identifier is disallowed in strict mode |
| 5864 // but "delete this" is. |
| 5865 ASSERT(strict_mode_flag() == kNonStrictMode || variable->is_this()); |
| 5856 Slot* slot = variable->AsSlot(); | 5866 Slot* slot = variable->AsSlot(); |
| 5857 if (variable->is_global()) { | 5867 if (variable->is_global()) { |
| 5858 LoadGlobal(); | 5868 LoadGlobal(); |
| 5859 frame_->EmitPush(Operand(variable->name())); | 5869 frame_->EmitPush(Operand(variable->name())); |
| 5860 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); | 5870 frame_->EmitPush(Operand(Smi::FromInt(kNonStrictMode))); |
| 5871 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 3); |
| 5861 frame_->EmitPush(r0); | 5872 frame_->EmitPush(r0); |
| 5862 | 5873 |
| 5863 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 5874 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 5864 // Delete from the context holding the named variable. | 5875 // Delete from the context holding the named variable. |
| 5865 frame_->EmitPush(cp); | 5876 frame_->EmitPush(cp); |
| 5866 frame_->EmitPush(Operand(variable->name())); | 5877 frame_->EmitPush(Operand(variable->name())); |
| 5867 frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); | 5878 frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 5868 frame_->EmitPush(r0); | 5879 frame_->EmitPush(r0); |
| 5869 | 5880 |
| 5870 } else { | 5881 } else { |
| (...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6671 // deferred code. | 6682 // deferred code. |
| 6672 __ BlockConstPoolFor(1); | 6683 __ BlockConstPoolFor(1); |
| 6673 } | 6684 } |
| 6674 } | 6685 } |
| 6675 | 6686 |
| 6676 | 6687 |
| 6677 class DeferredReferenceSetKeyedValue: public DeferredCode { | 6688 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 6678 public: | 6689 public: |
| 6679 DeferredReferenceSetKeyedValue(Register value, | 6690 DeferredReferenceSetKeyedValue(Register value, |
| 6680 Register key, | 6691 Register key, |
| 6681 Register receiver) | 6692 Register receiver, |
| 6682 : value_(value), key_(key), receiver_(receiver) { | 6693 StrictModeFlag strict_mode) |
| 6694 : value_(value), |
| 6695 key_(key), |
| 6696 receiver_(receiver), |
| 6697 strict_mode_(strict_mode) { |
| 6683 set_comment("[ DeferredReferenceSetKeyedValue"); | 6698 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 6684 } | 6699 } |
| 6685 | 6700 |
| 6686 virtual void Generate(); | 6701 virtual void Generate(); |
| 6687 | 6702 |
| 6688 private: | 6703 private: |
| 6689 Register value_; | 6704 Register value_; |
| 6690 Register key_; | 6705 Register key_; |
| 6691 Register receiver_; | 6706 Register receiver_; |
| 6707 StrictModeFlag strict_mode_; |
| 6692 }; | 6708 }; |
| 6693 | 6709 |
| 6694 | 6710 |
| 6695 void DeferredReferenceSetKeyedValue::Generate() { | 6711 void DeferredReferenceSetKeyedValue::Generate() { |
| 6696 Register scratch1 = VirtualFrame::scratch0(); | 6712 Register scratch1 = VirtualFrame::scratch0(); |
| 6697 Register scratch2 = VirtualFrame::scratch1(); | 6713 Register scratch2 = VirtualFrame::scratch1(); |
| 6698 __ DecrementCounter(COUNTERS->keyed_store_inline(), 1, scratch1, scratch2); | 6714 __ DecrementCounter(COUNTERS->keyed_store_inline(), 1, scratch1, scratch2); |
| 6699 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), | 6715 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), |
| 6700 1, scratch1, scratch2); | 6716 1, scratch1, scratch2); |
| 6701 | 6717 |
| 6702 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic | 6718 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic |
| 6703 // calling convention. | 6719 // calling convention. |
| 6704 if (value_.is(r1)) { | 6720 if (value_.is(r1)) { |
| 6705 __ Swap(r0, r1, ip); | 6721 __ Swap(r0, r1, ip); |
| 6706 } | 6722 } |
| 6707 ASSERT(receiver_.is(r2)); | 6723 ASSERT(receiver_.is(r2)); |
| 6708 | 6724 |
| 6709 // The rest of the instructions in the deferred code must be together. | 6725 // The rest of the instructions in the deferred code must be together. |
| 6710 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6726 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| 6711 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6727 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
| 6712 // r1 and r2. | 6728 // r1 and r2. |
| 6713 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 6729 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 6714 Builtins::KeyedStoreIC_Initialize)); | 6730 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict |
| 6731 : Builtins::KeyedStoreIC_Initialize)); |
| 6715 __ Call(ic, RelocInfo::CODE_TARGET); | 6732 __ Call(ic, RelocInfo::CODE_TARGET); |
| 6716 // The call must be followed by a nop instruction to indicate that the | 6733 // The call must be followed by a nop instruction to indicate that the |
| 6717 // keyed store has been inlined. | 6734 // keyed store has been inlined. |
| 6718 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6735 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
| 6719 | 6736 |
| 6720 // Block the constant pool for one more instruction after leaving this | 6737 // Block the constant pool for one more instruction after leaving this |
| 6721 // constant pool block scope to include the branch instruction ending the | 6738 // constant pool block scope to include the branch instruction ending the |
| 6722 // deferred code. | 6739 // deferred code. |
| 6723 __ BlockConstPoolFor(1); | 6740 __ BlockConstPoolFor(1); |
| 6724 } | 6741 } |
| 6725 } | 6742 } |
| 6726 | 6743 |
| 6727 | 6744 |
| 6728 class DeferredReferenceSetNamedValue: public DeferredCode { | 6745 class DeferredReferenceSetNamedValue: public DeferredCode { |
| 6729 public: | 6746 public: |
| 6730 DeferredReferenceSetNamedValue(Register value, | 6747 DeferredReferenceSetNamedValue(Register value, |
| 6731 Register receiver, | 6748 Register receiver, |
| 6732 Handle<String> name) | 6749 Handle<String> name, |
| 6733 : value_(value), receiver_(receiver), name_(name) { | 6750 StrictModeFlag strict_mode) |
| 6751 : value_(value), |
| 6752 receiver_(receiver), |
| 6753 name_(name), |
| 6754 strict_mode_(strict_mode) { |
| 6734 set_comment("[ DeferredReferenceSetNamedValue"); | 6755 set_comment("[ DeferredReferenceSetNamedValue"); |
| 6735 } | 6756 } |
| 6736 | 6757 |
| 6737 virtual void Generate(); | 6758 virtual void Generate(); |
| 6738 | 6759 |
| 6739 private: | 6760 private: |
| 6740 Register value_; | 6761 Register value_; |
| 6741 Register receiver_; | 6762 Register receiver_; |
| 6742 Handle<String> name_; | 6763 Handle<String> name_; |
| 6764 StrictModeFlag strict_mode_; |
| 6743 }; | 6765 }; |
| 6744 | 6766 |
| 6745 | 6767 |
| 6746 // Takes value in r0, receiver in r1 and returns the result (the | 6768 // Takes value in r0, receiver in r1 and returns the result (the |
| 6747 // value) in r0. | 6769 // value) in r0. |
| 6748 void DeferredReferenceSetNamedValue::Generate() { | 6770 void DeferredReferenceSetNamedValue::Generate() { |
| 6749 // Record the entry frame and spill. | 6771 // Record the entry frame and spill. |
| 6750 VirtualFrame copied_frame(*frame_state()->frame()); | 6772 VirtualFrame copied_frame(*frame_state()->frame()); |
| 6751 copied_frame.SpillAll(); | 6773 copied_frame.SpillAll(); |
| 6752 | 6774 |
| 6753 // Ensure value in r0, receiver in r1 to match store ic calling | 6775 // Ensure value in r0, receiver in r1 to match store ic calling |
| 6754 // convention. | 6776 // convention. |
| 6755 ASSERT(value_.is(r0) && receiver_.is(r1)); | 6777 ASSERT(value_.is(r0) && receiver_.is(r1)); |
| 6756 __ mov(r2, Operand(name_)); | 6778 __ mov(r2, Operand(name_)); |
| 6757 | 6779 |
| 6758 // The rest of the instructions in the deferred code must be together. | 6780 // The rest of the instructions in the deferred code must be together. |
| 6759 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6781 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| 6760 // Call keyed store IC. It has the arguments value, key and receiver in r0, | 6782 // Call keyed store IC. It has the arguments value, key and receiver in r0, |
| 6761 // r1 and r2. | 6783 // r1 and r2. |
| 6762 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 6784 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 6763 Builtins::StoreIC_Initialize)); | 6785 (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict |
| 6786 : Builtins::StoreIC_Initialize)); |
| 6764 __ Call(ic, RelocInfo::CODE_TARGET); | 6787 __ Call(ic, RelocInfo::CODE_TARGET); |
| 6765 // The call must be followed by a nop instruction to indicate that the | 6788 // The call must be followed by a nop instruction to indicate that the |
| 6766 // named store has been inlined. | 6789 // named store has been inlined. |
| 6767 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); | 6790 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); |
| 6768 | 6791 |
| 6769 // Go back to the frame we entered with. The instructions | 6792 // Go back to the frame we entered with. The instructions |
| 6770 // generated by this merge are skipped over by the inline store | 6793 // generated by this merge are skipped over by the inline store |
| 6771 // patching mechanism when looking for the branch instruction that | 6794 // patching mechanism when looking for the branch instruction that |
| 6772 // tells it where the code to patch is. | 6795 // tells it where the code to patch is. |
| 6773 copied_frame.MergeTo(frame_state()->frame()); | 6796 copied_frame.MergeTo(frame_state()->frame()); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6930 } | 6953 } |
| 6931 | 6954 |
| 6932 | 6955 |
| 6933 void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { | 6956 void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
| 6934 #ifdef DEBUG | 6957 #ifdef DEBUG |
| 6935 int expected_height = frame()->height() - (is_contextual ? 1 : 2); | 6958 int expected_height = frame()->height() - (is_contextual ? 1 : 2); |
| 6936 #endif | 6959 #endif |
| 6937 | 6960 |
| 6938 Result result; | 6961 Result result; |
| 6939 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { | 6962 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { |
| 6940 frame()->CallStoreIC(name, is_contextual); | 6963 frame()->CallStoreIC(name, is_contextual, strict_mode_flag()); |
| 6941 } else { | 6964 } else { |
| 6942 // Inline the in-object property case. | 6965 // Inline the in-object property case. |
| 6943 JumpTarget slow, done; | 6966 JumpTarget slow, done; |
| 6944 | 6967 |
| 6945 // Get the value and receiver from the stack. | 6968 // Get the value and receiver from the stack. |
| 6946 frame()->PopToR0(); | 6969 frame()->PopToR0(); |
| 6947 Register value = r0; | 6970 Register value = r0; |
| 6948 frame()->PopToR1(); | 6971 frame()->PopToR1(); |
| 6949 Register receiver = r1; | 6972 Register receiver = r1; |
| 6950 | 6973 |
| 6951 DeferredReferenceSetNamedValue* deferred = | 6974 DeferredReferenceSetNamedValue* deferred = |
| 6952 new DeferredReferenceSetNamedValue(value, receiver, name); | 6975 new DeferredReferenceSetNamedValue( |
| 6976 value, receiver, name, strict_mode_flag()); |
| 6953 | 6977 |
| 6954 // Check that the receiver is a heap object. | 6978 // Check that the receiver is a heap object. |
| 6955 __ tst(receiver, Operand(kSmiTagMask)); | 6979 __ tst(receiver, Operand(kSmiTagMask)); |
| 6956 deferred->Branch(eq); | 6980 deferred->Branch(eq); |
| 6957 | 6981 |
| 6958 // The following instructions are the part of the inlined | 6982 // The following instructions are the part of the inlined |
| 6959 // in-object property store code which can be patched. Therefore | 6983 // in-object property store code which can be patched. Therefore |
| 6960 // the exact number of instructions generated must be fixed, so | 6984 // the exact number of instructions generated must be fixed, so |
| 6961 // the constant pool is blocked while generating this code. | 6985 // the constant pool is blocked while generating this code. |
| 6962 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 6986 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7128 VirtualFrame::SpilledScope spilled(frame_); | 7152 VirtualFrame::SpilledScope spilled(frame_); |
| 7129 Register receiver = r2; | 7153 Register receiver = r2; |
| 7130 frame_->EmitPop(receiver); | 7154 frame_->EmitPop(receiver); |
| 7131 | 7155 |
| 7132 #ifdef DEBUG | 7156 #ifdef DEBUG |
| 7133 bool we_remembered_the_write_barrier = value_is_harmless; | 7157 bool we_remembered_the_write_barrier = value_is_harmless; |
| 7134 #endif | 7158 #endif |
| 7135 | 7159 |
| 7136 // The deferred code expects value, key and receiver in registers. | 7160 // The deferred code expects value, key and receiver in registers. |
| 7137 DeferredReferenceSetKeyedValue* deferred = | 7161 DeferredReferenceSetKeyedValue* deferred = |
| 7138 new DeferredReferenceSetKeyedValue(value, key, receiver); | 7162 new DeferredReferenceSetKeyedValue( |
| 7163 value, key, receiver, strict_mode_flag()); |
| 7139 | 7164 |
| 7140 // Check that the value is a smi. As this inlined code does not set the | 7165 // Check that the value is a smi. As this inlined code does not set the |
| 7141 // write barrier it is only possible to store smi values. | 7166 // write barrier it is only possible to store smi values. |
| 7142 if (!value_is_harmless) { | 7167 if (!value_is_harmless) { |
| 7143 // If the value is not likely to be a Smi then let's test the fixed array | 7168 // If the value is not likely to be a Smi then let's test the fixed array |
| 7144 // for new space instead. See below. | 7169 // for new space instead. See below. |
| 7145 if (wb_info == LIKELY_SMI) { | 7170 if (wb_info == LIKELY_SMI) { |
| 7146 __ tst(value, Operand(kSmiTagMask)); | 7171 __ tst(value, Operand(kSmiTagMask)); |
| 7147 deferred->Branch(ne); | 7172 deferred->Branch(ne); |
| 7148 #ifdef DEBUG | 7173 #ifdef DEBUG |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7213 | 7238 |
| 7214 // Make sure that the expected number of instructions are generated. | 7239 // Make sure that the expected number of instructions are generated. |
| 7215 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, | 7240 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, |
| 7216 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); | 7241 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
| 7217 } | 7242 } |
| 7218 | 7243 |
| 7219 ASSERT(we_remembered_the_write_barrier); | 7244 ASSERT(we_remembered_the_write_barrier); |
| 7220 | 7245 |
| 7221 deferred->BindExit(); | 7246 deferred->BindExit(); |
| 7222 } else { | 7247 } else { |
| 7223 frame()->CallKeyedStoreIC(); | 7248 frame()->CallKeyedStoreIC(strict_mode_flag()); |
| 7224 } | 7249 } |
| 7225 } | 7250 } |
| 7226 | 7251 |
| 7227 | 7252 |
| 7228 #ifdef DEBUG | 7253 #ifdef DEBUG |
| 7229 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 7254 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
| 7230 #endif | 7255 #endif |
| 7231 | 7256 |
| 7232 | 7257 |
| 7233 #undef __ | 7258 #undef __ |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7380 specialized_on_rhs_ ? "_ConstantRhs" : "", | 7405 specialized_on_rhs_ ? "_ConstantRhs" : "", |
| 7381 BinaryOpIC::GetName(runtime_operands_type_)); | 7406 BinaryOpIC::GetName(runtime_operands_type_)); |
| 7382 return name_; | 7407 return name_; |
| 7383 } | 7408 } |
| 7384 | 7409 |
| 7385 #undef __ | 7410 #undef __ |
| 7386 | 7411 |
| 7387 } } // namespace v8::internal | 7412 } } // namespace v8::internal |
| 7388 | 7413 |
| 7389 #endif // V8_TARGET_ARCH_ARM | 7414 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |