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

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

Issue 6594037: Strict Mode assignment to read only property. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: CR Feedback. Created 9 years, 9 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/api.cc ('k') | src/arm/full-codegen-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
(...skipping 1920 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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_mode)
6682 : value_(value),
6683 key_(key),
6684 receiver_(receiver),
6685 strict_mode_(strict_mode) {
6679 set_comment("[ DeferredReferenceSetKeyedValue"); 6686 set_comment("[ DeferredReferenceSetKeyedValue");
6680 } 6687 }
6681 6688
6682 virtual void Generate(); 6689 virtual void Generate();
6683 6690
6684 private: 6691 private:
6685 Register value_; 6692 Register value_;
6686 Register key_; 6693 Register key_;
6687 Register receiver_; 6694 Register receiver_;
6695 StrictModeFlag strict_mode_;
6688 }; 6696 };
6689 6697
6690 6698
6691 void DeferredReferenceSetKeyedValue::Generate() { 6699 void DeferredReferenceSetKeyedValue::Generate() {
6692 Register scratch1 = VirtualFrame::scratch0(); 6700 Register scratch1 = VirtualFrame::scratch0();
6693 Register scratch2 = VirtualFrame::scratch1(); 6701 Register scratch2 = VirtualFrame::scratch1();
6694 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2); 6702 __ DecrementCounter(&Counters::keyed_store_inline, 1, scratch1, scratch2);
6695 __ IncrementCounter( 6703 __ IncrementCounter(
6696 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2); 6704 &Counters::keyed_store_inline_miss, 1, scratch1, scratch2);
6697 6705
6698 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic 6706 // Ensure value in r0, key in r1 and receiver in r2 to match keyed store ic
6699 // calling convention. 6707 // calling convention.
6700 if (value_.is(r1)) { 6708 if (value_.is(r1)) {
6701 __ Swap(r0, r1, ip); 6709 __ Swap(r0, r1, ip);
6702 } 6710 }
6703 ASSERT(receiver_.is(r2)); 6711 ASSERT(receiver_.is(r2));
6704 6712
6705 // The rest of the instructions in the deferred code must be together. 6713 // The rest of the instructions in the deferred code must be together.
6706 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6714 { Assembler::BlockConstPoolScope block_const_pool(masm_);
6707 // Call keyed store IC. It has the arguments value, key and receiver in r0, 6715 // Call keyed store IC. It has the arguments value, key and receiver in r0,
6708 // r1 and r2. 6716 // r1 and r2.
6709 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6717 Handle<Code> ic(Builtins::builtin(
6718 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
6719 : Builtins::KeyedStoreIC_Initialize));
6710 __ Call(ic, RelocInfo::CODE_TARGET); 6720 __ Call(ic, RelocInfo::CODE_TARGET);
6711 // The call must be followed by a nop instruction to indicate that the 6721 // The call must be followed by a nop instruction to indicate that the
6712 // keyed store has been inlined. 6722 // keyed store has been inlined.
6713 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); 6723 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
6714 6724
6715 // Block the constant pool for one more instruction after leaving this 6725 // Block the constant pool for one more instruction after leaving this
6716 // constant pool block scope to include the branch instruction ending the 6726 // constant pool block scope to include the branch instruction ending the
6717 // deferred code. 6727 // deferred code.
6718 __ BlockConstPoolFor(1); 6728 __ BlockConstPoolFor(1);
6719 } 6729 }
6720 } 6730 }
6721 6731
6722 6732
6723 class DeferredReferenceSetNamedValue: public DeferredCode { 6733 class DeferredReferenceSetNamedValue: public DeferredCode {
6724 public: 6734 public:
6725 DeferredReferenceSetNamedValue(Register value, 6735 DeferredReferenceSetNamedValue(Register value,
6726 Register receiver, 6736 Register receiver,
6727 Handle<String> name) 6737 Handle<String> name,
6728 : value_(value), receiver_(receiver), name_(name) { 6738 StrictModeFlag strict_mode)
6739 : value_(value),
6740 receiver_(receiver),
6741 name_(name),
6742 strict_mode_(strict_mode) {
6729 set_comment("[ DeferredReferenceSetNamedValue"); 6743 set_comment("[ DeferredReferenceSetNamedValue");
6730 } 6744 }
6731 6745
6732 virtual void Generate(); 6746 virtual void Generate();
6733 6747
6734 private: 6748 private:
6735 Register value_; 6749 Register value_;
6736 Register receiver_; 6750 Register receiver_;
6737 Handle<String> name_; 6751 Handle<String> name_;
6752 StrictModeFlag strict_mode_;
6738 }; 6753 };
6739 6754
6740 6755
6741 // Takes value in r0, receiver in r1 and returns the result (the 6756 // Takes value in r0, receiver in r1 and returns the result (the
6742 // value) in r0. 6757 // value) in r0.
6743 void DeferredReferenceSetNamedValue::Generate() { 6758 void DeferredReferenceSetNamedValue::Generate() {
6744 // Record the entry frame and spill. 6759 // Record the entry frame and spill.
6745 VirtualFrame copied_frame(*frame_state()->frame()); 6760 VirtualFrame copied_frame(*frame_state()->frame());
6746 copied_frame.SpillAll(); 6761 copied_frame.SpillAll();
6747 6762
6748 // Ensure value in r0, receiver in r1 to match store ic calling 6763 // Ensure value in r0, receiver in r1 to match store ic calling
6749 // convention. 6764 // convention.
6750 ASSERT(value_.is(r0) && receiver_.is(r1)); 6765 ASSERT(value_.is(r0) && receiver_.is(r1));
6751 __ mov(r2, Operand(name_)); 6766 __ mov(r2, Operand(name_));
6752 6767
6753 // The rest of the instructions in the deferred code must be together. 6768 // The rest of the instructions in the deferred code must be together.
6754 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6769 { Assembler::BlockConstPoolScope block_const_pool(masm_);
6755 // Call keyed store IC. It has the arguments value, key and receiver in r0, 6770 // Call keyed store IC. It has the arguments value, key and receiver in r0,
6756 // r1 and r2. 6771 // r1 and r2.
6757 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 6772 Handle<Code> ic(Builtins::builtin(
6773 (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
6774 : Builtins::StoreIC_Initialize));
6758 __ Call(ic, RelocInfo::CODE_TARGET); 6775 __ Call(ic, RelocInfo::CODE_TARGET);
6759 // The call must be followed by a nop instruction to indicate that the 6776 // The call must be followed by a nop instruction to indicate that the
6760 // named store has been inlined. 6777 // named store has been inlined.
6761 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED); 6778 __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
6762 6779
6763 // Go back to the frame we entered with. The instructions 6780 // Go back to the frame we entered with. The instructions
6764 // generated by this merge are skipped over by the inline store 6781 // generated by this merge are skipped over by the inline store
6765 // patching mechanism when looking for the branch instruction that 6782 // patching mechanism when looking for the branch instruction that
6766 // tells it where the code to patch is. 6783 // tells it where the code to patch is.
6767 copied_frame.MergeTo(frame_state()->frame()); 6784 copied_frame.MergeTo(frame_state()->frame());
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
6936 // Inline the in-object property case. 6953 // Inline the in-object property case.
6937 JumpTarget slow, done; 6954 JumpTarget slow, done;
6938 6955
6939 // Get the value and receiver from the stack. 6956 // Get the value and receiver from the stack.
6940 frame()->PopToR0(); 6957 frame()->PopToR0();
6941 Register value = r0; 6958 Register value = r0;
6942 frame()->PopToR1(); 6959 frame()->PopToR1();
6943 Register receiver = r1; 6960 Register receiver = r1;
6944 6961
6945 DeferredReferenceSetNamedValue* deferred = 6962 DeferredReferenceSetNamedValue* deferred =
6946 new DeferredReferenceSetNamedValue(value, receiver, name); 6963 new DeferredReferenceSetNamedValue(
6964 value, receiver, name, strict_mode_flag());
6947 6965
6948 // Check that the receiver is a heap object. 6966 // Check that the receiver is a heap object.
6949 __ tst(receiver, Operand(kSmiTagMask)); 6967 __ tst(receiver, Operand(kSmiTagMask));
6950 deferred->Branch(eq); 6968 deferred->Branch(eq);
6951 6969
6952 // The following instructions are the part of the inlined 6970 // The following instructions are the part of the inlined
6953 // in-object property store code which can be patched. Therefore 6971 // in-object property store code which can be patched. Therefore
6954 // the exact number of instructions generated must be fixed, so 6972 // the exact number of instructions generated must be fixed, so
6955 // the constant pool is blocked while generating this code. 6973 // the constant pool is blocked while generating this code.
6956 { Assembler::BlockConstPoolScope block_const_pool(masm_); 6974 { Assembler::BlockConstPoolScope block_const_pool(masm_);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
7122 VirtualFrame::SpilledScope spilled(frame_); 7140 VirtualFrame::SpilledScope spilled(frame_);
7123 Register receiver = r2; 7141 Register receiver = r2;
7124 frame_->EmitPop(receiver); 7142 frame_->EmitPop(receiver);
7125 7143
7126 #ifdef DEBUG 7144 #ifdef DEBUG
7127 bool we_remembered_the_write_barrier = value_is_harmless; 7145 bool we_remembered_the_write_barrier = value_is_harmless;
7128 #endif 7146 #endif
7129 7147
7130 // The deferred code expects value, key and receiver in registers. 7148 // The deferred code expects value, key and receiver in registers.
7131 DeferredReferenceSetKeyedValue* deferred = 7149 DeferredReferenceSetKeyedValue* deferred =
7132 new DeferredReferenceSetKeyedValue(value, key, receiver); 7150 new DeferredReferenceSetKeyedValue(
7151 value, key, receiver, strict_mode_flag());
7133 7152
7134 // Check that the value is a smi. As this inlined code does not set the 7153 // 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. 7154 // write barrier it is only possible to store smi values.
7136 if (!value_is_harmless) { 7155 if (!value_is_harmless) {
7137 // If the value is not likely to be a Smi then let's test the fixed array 7156 // If the value is not likely to be a Smi then let's test the fixed array
7138 // for new space instead. See below. 7157 // for new space instead. See below.
7139 if (wb_info == LIKELY_SMI) { 7158 if (wb_info == LIKELY_SMI) {
7140 __ tst(value, Operand(kSmiTagMask)); 7159 __ tst(value, Operand(kSmiTagMask));
7141 deferred->Branch(ne); 7160 deferred->Branch(ne);
7142 #ifdef DEBUG 7161 #ifdef DEBUG
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
7207 7226
7208 // Make sure that the expected number of instructions are generated. 7227 // Make sure that the expected number of instructions are generated.
7209 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch, 7228 ASSERT_EQ(kInlinedKeyedStoreInstructionsAfterPatch,
7210 masm_->InstructionsGeneratedSince(&check_inlined_codesize)); 7229 masm_->InstructionsGeneratedSince(&check_inlined_codesize));
7211 } 7230 }
7212 7231
7213 ASSERT(we_remembered_the_write_barrier); 7232 ASSERT(we_remembered_the_write_barrier);
7214 7233
7215 deferred->BindExit(); 7234 deferred->BindExit();
7216 } else { 7235 } else {
7217 frame()->CallKeyedStoreIC(); 7236 frame()->CallKeyedStoreIC(strict_mode_flag());
7218 } 7237 }
7219 } 7238 }
7220 7239
7221 7240
7222 #ifdef DEBUG 7241 #ifdef DEBUG
7223 bool CodeGenerator::HasValidEntryRegisters() { return true; } 7242 bool CodeGenerator::HasValidEntryRegisters() { return true; }
7224 #endif 7243 #endif
7225 7244
7226 7245
7227 #undef __ 7246 #undef __
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
7375 BinaryOpIC::GetName(runtime_operands_type_)); 7394 BinaryOpIC::GetName(runtime_operands_type_));
7376 return name_; 7395 return name_;
7377 } 7396 }
7378 7397
7379 7398
7380 #undef __ 7399 #undef __
7381 7400
7382 } } // namespace v8::internal 7401 } } // namespace v8::internal
7383 7402
7384 #endif // V8_TARGET_ARCH_ARM 7403 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/api.cc ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698