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

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

Powered by Google App Engine
This is Rietveld 408576698