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

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

Issue 6576024: (early draft) Strict mode - throw exception on assignment to read only property. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Assign to read only property in strict mode. 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)
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
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
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
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
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
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