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

Side by Side Diff: src/ia32/codegen-ia32.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: 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
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 5241 matching lines...) Expand 10 before | Expand all | Expand 10 after
5252 // context slot declaration, but we cannot initialize it at the same 5252 // context slot declaration, but we cannot initialize it at the same
5253 // time, because the const declaration may be at the end of the eval 5253 // time, because the const declaration may be at the end of the eval
5254 // code (sigh...) and the const variable may have been used before 5254 // code (sigh...) and the const variable may have been used before
5255 // (where its value is 'undefined'). Thus, we can only do the 5255 // (where its value is 'undefined'). Thus, we can only do the
5256 // initialization when we actually encounter the expression and when 5256 // initialization when we actually encounter the expression and when
5257 // the expression operands are defined and valid, and thus we need the 5257 // the expression operands are defined and valid, and thus we need the
5258 // split into 2 operations: declaration of the context slot followed 5258 // split into 2 operations: declaration of the context slot followed
5259 // by initialization. 5259 // by initialization.
5260 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 5260 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
5261 } else { 5261 } else {
5262 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 5262 frame_->Push(Smi::FromInt(strict_mode_flag()));
5263 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
5263 } 5264 }
5264 // Storing a variable must keep the (new) value on the expression 5265 // Storing a variable must keep the (new) value on the expression
5265 // stack. This is necessary for compiling chained assignment 5266 // stack. This is necessary for compiling chained assignment
5266 // expressions. 5267 // expressions.
5267 frame_->Push(&value); 5268 frame_->Push(&value);
5268 5269
5269 } else { 5270 } else {
5270 ASSERT(!slot->var()->is_dynamic()); 5271 ASSERT(!slot->var()->is_dynamic());
5271 5272
5272 JumpTarget exit; 5273 JumpTarget exit;
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
5601 break; 5602 break;
5602 } 5603 }
5603 // Fall through 5604 // Fall through
5604 } 5605 }
5605 case ObjectLiteral::Property::PROTOTYPE: { 5606 case ObjectLiteral::Property::PROTOTYPE: {
5606 // Duplicate the object as an argument to the runtime call. 5607 // Duplicate the object as an argument to the runtime call.
5607 frame_->Dup(); 5608 frame_->Dup();
5608 Load(property->key()); 5609 Load(property->key());
5609 Load(property->value()); 5610 Load(property->value());
5610 if (property->emit_store()) { 5611 if (property->emit_store()) {
5612 frame_->Push(Smi::FromInt(NONE)); // PropertyAttributes
5611 // Ignore the result. 5613 // Ignore the result.
5612 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 5614 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
5613 } else { 5615 } else {
5614 frame_->Drop(3); 5616 frame_->Drop(3);
5615 } 5617 }
5616 break; 5618 break;
5617 } 5619 }
5618 case ObjectLiteral::Property::SETTER: { 5620 case ObjectLiteral::Property::SETTER: {
5619 // Duplicate the object as an argument to the runtime call. 5621 // Duplicate the object as an argument to the runtime call.
5620 frame_->Dup(); 5622 frame_->Dup();
5621 Load(property->key()); 5623 Load(property->key());
5622 frame_->Push(Smi::FromInt(1)); 5624 frame_->Push(Smi::FromInt(1));
(...skipping 3828 matching lines...) Expand 10 before | Expand all | Expand 10 after
9451 9453
9452 if (!dst_.is(eax)) __ mov(dst_, eax); 9454 if (!dst_.is(eax)) __ mov(dst_, eax);
9453 } 9455 }
9454 9456
9455 9457
9456 class DeferredReferenceSetKeyedValue: public DeferredCode { 9458 class DeferredReferenceSetKeyedValue: public DeferredCode {
9457 public: 9459 public:
9458 DeferredReferenceSetKeyedValue(Register value, 9460 DeferredReferenceSetKeyedValue(Register value,
9459 Register key, 9461 Register key,
9460 Register receiver, 9462 Register receiver,
9461 Register scratch) 9463 Register scratch,
9464 StrictModeFlag strict)
9462 : value_(value), 9465 : value_(value),
9463 key_(key), 9466 key_(key),
9464 receiver_(receiver), 9467 receiver_(receiver),
9465 scratch_(scratch) { 9468 scratch_(scratch),
9469 strict_(strict) {
9466 set_comment("[ DeferredReferenceSetKeyedValue"); 9470 set_comment("[ DeferredReferenceSetKeyedValue");
9467 } 9471 }
9468 9472
9469 virtual void Generate(); 9473 virtual void Generate();
9470 9474
9471 Label* patch_site() { return &patch_site_; } 9475 Label* patch_site() { return &patch_site_; }
9472 9476
9473 private: 9477 private:
9474 Register value_; 9478 Register value_;
9475 Register key_; 9479 Register key_;
9476 Register receiver_; 9480 Register receiver_;
9477 Register scratch_; 9481 Register scratch_;
9478 Label patch_site_; 9482 Label patch_site_;
9483 StrictModeFlag strict_;
9479 }; 9484 };
9480 9485
9481 9486
9482 void DeferredReferenceSetKeyedValue::Generate() { 9487 void DeferredReferenceSetKeyedValue::Generate() {
9483 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 9488 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
9484 // Move value_ to eax, key_ to ecx, and receiver_ to edx. 9489 // Move value_ to eax, key_ to ecx, and receiver_ to edx.
9485 Register old_value = value_; 9490 Register old_value = value_;
9486 9491
9487 // First, move value to eax. 9492 // First, move value to eax.
9488 if (!value_.is(eax)) { 9493 if (!value_.is(eax)) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
9527 } 9532 }
9528 } 9533 }
9529 } else { // Key is not in edx or ecx. 9534 } else { // Key is not in edx or ecx.
9530 if (!receiver_.is(edx)) { 9535 if (!receiver_.is(edx)) {
9531 __ mov(edx, receiver_); 9536 __ mov(edx, receiver_);
9532 } 9537 }
9533 __ mov(ecx, key_); 9538 __ mov(ecx, key_);
9534 } 9539 }
9535 9540
9536 // Call the IC stub. 9541 // Call the IC stub.
9537 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 9542 Handle<Code> ic(Builtins::builtin(
9543 strict_ == kStrictMode ? Builtins::KeyedStoreIC_Initialize_Strict
9544 : Builtins::KeyedStoreIC_Initialize));
9538 __ call(ic, RelocInfo::CODE_TARGET); 9545 __ call(ic, RelocInfo::CODE_TARGET);
9539 // The delta from the start of the map-compare instruction to the 9546 // The delta from the start of the map-compare instruction to the
9540 // test instruction. We use masm_-> directly here instead of the 9547 // test instruction. We use masm_-> directly here instead of the
9541 // __ macro because the macro sometimes uses macro expansion to turn 9548 // __ macro because the macro sometimes uses macro expansion to turn
9542 // into something that can't return a value. This is encountered 9549 // into something that can't return a value. This is encountered
9543 // when doing generated code coverage tests. 9550 // when doing generated code coverage tests.
9544 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 9551 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
9545 // Here we use masm_-> instead of the __ macro because this is the 9552 // Here we use masm_-> instead of the __ macro because this is the
9546 // instruction that gets patched and coverage code gets in the way. 9553 // instruction that gets patched and coverage code gets in the way.
9547 masm_->test(eax, Immediate(-delta_to_patch_site)); 9554 masm_->test(eax, Immediate(-delta_to_patch_site));
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
9889 9896
9890 // Make sure that value, key and receiver are in registers. 9897 // Make sure that value, key and receiver are in registers.
9891 result.ToRegister(); 9898 result.ToRegister();
9892 key.ToRegister(); 9899 key.ToRegister();
9893 receiver.ToRegister(); 9900 receiver.ToRegister();
9894 9901
9895 DeferredReferenceSetKeyedValue* deferred = 9902 DeferredReferenceSetKeyedValue* deferred =
9896 new DeferredReferenceSetKeyedValue(result.reg(), 9903 new DeferredReferenceSetKeyedValue(result.reg(),
9897 key.reg(), 9904 key.reg(),
9898 receiver.reg(), 9905 receiver.reg(),
9899 tmp.reg()); 9906 tmp.reg(),
9907 strict_mode_flag());
9900 9908
9901 // Check that the receiver is not a smi. 9909 // Check that the receiver is not a smi.
9902 __ test(receiver.reg(), Immediate(kSmiTagMask)); 9910 __ test(receiver.reg(), Immediate(kSmiTagMask));
9903 deferred->Branch(zero); 9911 deferred->Branch(zero);
9904 9912
9905 // Check that the key is a smi. 9913 // Check that the key is a smi.
9906 if (!key.is_smi()) { 9914 if (!key.is_smi()) {
9907 __ test(key.reg(), Immediate(kSmiTagMask)); 9915 __ test(key.reg(), Immediate(kSmiTagMask));
9908 deferred->Branch(not_zero); 9916 deferred->Branch(not_zero);
9909 } else { 9917 } else {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
9944 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 9952 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
9945 Immediate(Factory::fixed_array_map())); 9953 Immediate(Factory::fixed_array_map()));
9946 deferred->Branch(not_equal); 9954 deferred->Branch(not_equal);
9947 9955
9948 // Store the value. 9956 // Store the value.
9949 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg()); 9957 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg());
9950 __ IncrementCounter(&Counters::keyed_store_inline, 1); 9958 __ IncrementCounter(&Counters::keyed_store_inline, 1);
9951 9959
9952 deferred->BindExit(); 9960 deferred->BindExit();
9953 } else { 9961 } else {
9954 result = frame()->CallKeyedStoreIC(); 9962 result = frame()->CallKeyedStoreIC(strict_mode_flag());
9955 // Make sure that we do not have a test instruction after the 9963 // Make sure that we do not have a test instruction after the
9956 // call. A test instruction after the call is used to 9964 // call. A test instruction after the call is used to
9957 // indicate that we have generated an inline version of the 9965 // indicate that we have generated an inline version of the
9958 // keyed store. 9966 // keyed store.
9959 __ nop(); 9967 __ nop();
9960 } 9968 }
9961 ASSERT(frame()->height() == original_height - 3); 9969 ASSERT(frame()->height() == original_height - 3);
9962 return result; 9970 return result;
9963 } 9971 }
9964 9972
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
10324 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); 10332 memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size);
10325 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); 10333 CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size);
10326 return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress()); 10334 return FUNCTION_CAST<MemCopyFunction>(chunk->GetStartAddress());
10327 } 10335 }
10328 10336
10329 #undef __ 10337 #undef __
10330 10338
10331 } } // namespace v8::internal 10339 } } // namespace v8::internal
10332 10340
10333 #endif // V8_TARGET_ARCH_IA32 10341 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698