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

Side by Side Diff: src/x64/codegen-x64.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, 10 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/stub-cache.cc ('k') | src/x64/full-codegen-x64.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after
2740 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 2740 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
2741 // Call the runtime to declare the globals. The inevitable call 2741 // Call the runtime to declare the globals. The inevitable call
2742 // will sync frame elements to memory anyway, so we do it eagerly to 2742 // will sync frame elements to memory anyway, so we do it eagerly to
2743 // allow us to push the arguments directly into place. 2743 // allow us to push the arguments directly into place.
2744 frame_->SyncRange(0, frame_->element_count() - 1); 2744 frame_->SyncRange(0, frame_->element_count() - 1);
2745 2745
2746 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); 2746 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT);
2747 frame_->EmitPush(rsi); // The context is the first argument. 2747 frame_->EmitPush(rsi); // The context is the first argument.
2748 frame_->EmitPush(kScratchRegister); 2748 frame_->EmitPush(kScratchRegister);
2749 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); 2749 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
2750 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 2750 frame_->EmitPush(Smi::FromInt(strict_mode_flag()));
2751 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
2751 // Return value is ignored. 2752 // Return value is ignored.
2752 } 2753 }
2753 2754
2754 2755
2755 void CodeGenerator::VisitDeclaration(Declaration* node) { 2756 void CodeGenerator::VisitDeclaration(Declaration* node) {
2756 Comment cmnt(masm_, "[ Declaration"); 2757 Comment cmnt(masm_, "[ Declaration");
2757 Variable* var = node->proxy()->var(); 2758 Variable* var = node->proxy()->var();
2758 ASSERT(var != NULL); // must have been resolved 2759 ASSERT(var != NULL); // must have been resolved
2759 Slot* slot = var->AsSlot(); 2760 Slot* slot = var->AsSlot();
2760 2761
(...skipping 1837 matching lines...) Expand 10 before | Expand all | Expand 10 after
4598 // context slot declaration, but we cannot initialize it at the same 4599 // context slot declaration, but we cannot initialize it at the same
4599 // time, because the const declaration may be at the end of the eval 4600 // time, because the const declaration may be at the end of the eval
4600 // code (sigh...) and the const variable may have been used before 4601 // code (sigh...) and the const variable may have been used before
4601 // (where its value is 'undefined'). Thus, we can only do the 4602 // (where its value is 'undefined'). Thus, we can only do the
4602 // initialization when we actually encounter the expression and when 4603 // initialization when we actually encounter the expression and when
4603 // the expression operands are defined and valid, and thus we need the 4604 // the expression operands are defined and valid, and thus we need the
4604 // split into 2 operations: declaration of the context slot followed 4605 // split into 2 operations: declaration of the context slot followed
4605 // by initialization. 4606 // by initialization.
4606 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 4607 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
4607 } else { 4608 } else {
4608 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 4609 frame_->Push(Smi::FromInt(strict_mode_flag()));
4610 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
4609 } 4611 }
4610 // Storing a variable must keep the (new) value on the expression 4612 // Storing a variable must keep the (new) value on the expression
4611 // stack. This is necessary for compiling chained assignment 4613 // stack. This is necessary for compiling chained assignment
4612 // expressions. 4614 // expressions.
4613 frame_->Push(&value); 4615 frame_->Push(&value);
4614 } else { 4616 } else {
4615 ASSERT(!slot->var()->is_dynamic()); 4617 ASSERT(!slot->var()->is_dynamic());
4616 4618
4617 JumpTarget exit; 4619 JumpTarget exit;
4618 if (init_state == CONST_INIT) { 4620 if (init_state == CONST_INIT) {
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
4907 break; 4909 break;
4908 } 4910 }
4909 // Fall through 4911 // Fall through
4910 } 4912 }
4911 case ObjectLiteral::Property::PROTOTYPE: { 4913 case ObjectLiteral::Property::PROTOTYPE: {
4912 // Duplicate the object as an argument to the runtime call. 4914 // Duplicate the object as an argument to the runtime call.
4913 frame_->Dup(); 4915 frame_->Dup();
4914 Load(property->key()); 4916 Load(property->key());
4915 Load(property->value()); 4917 Load(property->value());
4916 if (property->emit_store()) { 4918 if (property->emit_store()) {
4919 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes
4917 // Ignore the result. 4920 // Ignore the result.
4918 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 4921 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
4919 } else { 4922 } else {
4920 frame_->Drop(3); 4923 frame_->Drop(3);
4921 } 4924 }
4922 break; 4925 break;
4923 } 4926 }
4924 case ObjectLiteral::Property::SETTER: { 4927 case ObjectLiteral::Property::SETTER: {
4925 // Duplicate the object as an argument to the runtime call. 4928 // Duplicate the object as an argument to the runtime call.
4926 frame_->Dup(); 4929 frame_->Dup();
4927 Load(property->key()); 4930 Load(property->key());
4928 frame_->Push(Smi::FromInt(1)); 4931 frame_->Push(Smi::FromInt(1));
(...skipping 3139 matching lines...) Expand 10 before | Expand all | Expand 10 after
8068 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); 8071 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
8069 8072
8070 if (!dst_.is(rax)) __ movq(dst_, rax); 8073 if (!dst_.is(rax)) __ movq(dst_, rax);
8071 } 8074 }
8072 8075
8073 8076
8074 class DeferredReferenceSetKeyedValue: public DeferredCode { 8077 class DeferredReferenceSetKeyedValue: public DeferredCode {
8075 public: 8078 public:
8076 DeferredReferenceSetKeyedValue(Register value, 8079 DeferredReferenceSetKeyedValue(Register value,
8077 Register key, 8080 Register key,
8078 Register receiver) 8081 Register receiver,
8079 : value_(value), key_(key), receiver_(receiver) { 8082 StrictModeFlag strict)
8083 : value_(value), key_(key), receiver_(receiver), strict_(strict) {
8080 set_comment("[ DeferredReferenceSetKeyedValue"); 8084 set_comment("[ DeferredReferenceSetKeyedValue");
8081 } 8085 }
8082 8086
8083 virtual void Generate(); 8087 virtual void Generate();
8084 8088
8085 Label* patch_site() { return &patch_site_; } 8089 Label* patch_site() { return &patch_site_; }
8086 8090
8087 private: 8091 private:
8088 Register value_; 8092 Register value_;
8089 Register key_; 8093 Register key_;
8090 Register receiver_; 8094 Register receiver_;
8091 Label patch_site_; 8095 Label patch_site_;
8096 StrictModeFlag strict_;
8092 }; 8097 };
8093 8098
8094 8099
8095 void DeferredReferenceSetKeyedValue::Generate() { 8100 void DeferredReferenceSetKeyedValue::Generate() {
8096 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 8101 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
8097 // Move value, receiver, and key to registers rax, rdx, and rcx, as 8102 // Move value, receiver, and key to registers rax, rdx, and rcx, as
8098 // the IC stub expects. 8103 // the IC stub expects.
8099 // Move value to rax, using xchg if the receiver or key is in rax. 8104 // Move value to rax, using xchg if the receiver or key is in rax.
8100 if (!value_.is(rax)) { 8105 if (!value_.is(rax)) {
8101 if (!receiver_.is(rax) && !key_.is(rax)) { 8106 if (!receiver_.is(rax) && !key_.is(rax)) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
8133 __ movq(rcx, key_); 8138 __ movq(rcx, key_);
8134 } 8139 }
8135 } else if (key_.is(rcx)) { 8140 } else if (key_.is(rcx)) {
8136 __ movq(rdx, receiver_); 8141 __ movq(rdx, receiver_);
8137 } else { 8142 } else {
8138 __ movq(rcx, key_); 8143 __ movq(rcx, key_);
8139 __ movq(rdx, receiver_); 8144 __ movq(rdx, receiver_);
8140 } 8145 }
8141 8146
8142 // Call the IC stub. 8147 // Call the IC stub.
8143 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 8148 Handle<Code> ic(Builtins::builtin(
8149 strict_ == kStrictMode ? Builtins::KeyedStoreIC_Initialize_Strict
8150 : Builtins::KeyedStoreIC_Initialize));
8144 __ Call(ic, RelocInfo::CODE_TARGET); 8151 __ Call(ic, RelocInfo::CODE_TARGET);
8145 // The delta from the start of the map-compare instructions (initial movq) 8152 // The delta from the start of the map-compare instructions (initial movq)
8146 // to the test instruction. We use masm_-> directly here instead of the 8153 // to the test instruction. We use masm_-> directly here instead of the
8147 // __ macro because the macro sometimes uses macro expansion to turn 8154 // __ macro because the macro sometimes uses macro expansion to turn
8148 // into something that can't return a value. This is encountered 8155 // into something that can't return a value. This is encountered
8149 // when doing generated code coverage tests. 8156 // when doing generated code coverage tests.
8150 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 8157 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
8151 // Here we use masm_-> instead of the __ macro because this is the 8158 // Here we use masm_-> instead of the __ macro because this is the
8152 // instruction that gets patched and coverage code gets in the way. 8159 // instruction that gets patched and coverage code gets in the way.
8153 masm_->testl(rax, Immediate(-delta_to_patch_site)); 8160 masm_->testl(rax, Immediate(-delta_to_patch_site));
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
8474 bool value_is_constant = result.is_constant(); 8481 bool value_is_constant = result.is_constant();
8475 8482
8476 // Make sure that value, key and receiver are in registers. 8483 // Make sure that value, key and receiver are in registers.
8477 result.ToRegister(); 8484 result.ToRegister();
8478 key.ToRegister(); 8485 key.ToRegister();
8479 receiver.ToRegister(); 8486 receiver.ToRegister();
8480 8487
8481 DeferredReferenceSetKeyedValue* deferred = 8488 DeferredReferenceSetKeyedValue* deferred =
8482 new DeferredReferenceSetKeyedValue(result.reg(), 8489 new DeferredReferenceSetKeyedValue(result.reg(),
8483 key.reg(), 8490 key.reg(),
8484 receiver.reg()); 8491 receiver.reg(),
8492 strict_mode_flag());
8485 8493
8486 // Check that the receiver is not a smi. 8494 // Check that the receiver is not a smi.
8487 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 8495 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
8488 8496
8489 // Check that the key is a smi. 8497 // Check that the key is a smi.
8490 if (!key.is_smi()) { 8498 if (!key.is_smi()) {
8491 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); 8499 __ JumpIfNotSmi(key.reg(), deferred->entry_label());
8492 } else if (FLAG_debug_code) { 8500 } else if (FLAG_debug_code) {
8493 __ AbortIfNotSmi(key.reg()); 8501 __ AbortIfNotSmi(key.reg());
8494 } 8502 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
8536 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); 8544 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8537 __ movq(FieldOperand(tmp.reg(), 8545 __ movq(FieldOperand(tmp.reg(),
8538 index.reg, 8546 index.reg,
8539 index.scale, 8547 index.scale,
8540 FixedArray::kHeaderSize), 8548 FixedArray::kHeaderSize),
8541 result.reg()); 8549 result.reg());
8542 __ IncrementCounter(&Counters::keyed_store_inline, 1); 8550 __ IncrementCounter(&Counters::keyed_store_inline, 1);
8543 8551
8544 deferred->BindExit(); 8552 deferred->BindExit();
8545 } else { 8553 } else {
8546 result = frame()->CallKeyedStoreIC(); 8554 result = frame()->CallKeyedStoreIC(strict_mode_flag());
8547 // Make sure that we do not have a test instruction after the 8555 // Make sure that we do not have a test instruction after the
8548 // call. A test instruction after the call is used to 8556 // call. A test instruction after the call is used to
8549 // indicate that we have generated an inline version of the 8557 // indicate that we have generated an inline version of the
8550 // keyed store. 8558 // keyed store.
8551 __ nop(); 8559 __ nop();
8552 } 8560 }
8553 ASSERT(frame()->height() == original_height - 3); 8561 ASSERT(frame()->height() == original_height - 3);
8554 return result; 8562 return result;
8555 } 8563 }
8556 8564
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
8815 } 8823 }
8816 8824
8817 #endif 8825 #endif
8818 8826
8819 8827
8820 #undef __ 8828 #undef __
8821 8829
8822 } } // namespace v8::internal 8830 } } // namespace v8::internal
8823 8831
8824 #endif // V8_TARGET_ARCH_X64 8832 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/stub-cache.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698