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

Side by Side Diff: src/arm/full-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/arm/codegen-arm.cc ('k') | src/arm/ic-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 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 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 VisitForAccumulatorValue(function); 776 VisitForAccumulatorValue(function);
777 __ pop(r2); 777 __ pop(r2);
778 } else { 778 } else {
779 __ mov(r2, r0); 779 __ mov(r2, r0);
780 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 780 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
781 } 781 }
782 ASSERT(prop->key()->AsLiteral() != NULL && 782 ASSERT(prop->key()->AsLiteral() != NULL &&
783 prop->key()->AsLiteral()->handle()->IsSmi()); 783 prop->key()->AsLiteral()->handle()->IsSmi());
784 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); 784 __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
785 785
786 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 786 Handle<Code> ic(Builtins::builtin(is_strict()
787 ? Builtins::KeyedStoreIC_Initialize_Strict
788 : Builtins::KeyedStoreIC_Initialize));
787 EmitCallIC(ic, RelocInfo::CODE_TARGET); 789 EmitCallIC(ic, RelocInfo::CODE_TARGET);
788 // Value in r0 is ignored (declarations are statements). 790 // Value in r0 is ignored (declarations are statements).
789 } 791 }
790 } 792 }
791 } 793 }
792 794
793 795
794 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 796 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
795 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 797 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
796 } 798 }
797 799
798 800
799 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 801 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
800 // Call the runtime to declare the globals. 802 // Call the runtime to declare the globals.
801 // The context is the first argument. 803 // The context is the first argument.
802 __ mov(r1, Operand(pairs)); 804 __ mov(r2, Operand(pairs));
803 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 805 __ mov(r1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
804 __ Push(cp, r1, r0); 806 __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
805 __ CallRuntime(Runtime::kDeclareGlobals, 3); 807 __ Push(cp, r2, r1, r0);
808 __ CallRuntime(Runtime::kDeclareGlobals, 4);
806 // Return value is ignored. 809 // Return value is ignored.
807 } 810 }
808 811
809 812
810 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 813 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
811 Comment cmnt(masm_, "[ SwitchStatement"); 814 Comment cmnt(masm_, "[ SwitchStatement");
812 Breakable nested_statement(this, stmt); 815 Breakable nested_statement(this, stmt);
813 SetStatementPosition(stmt); 816 SetStatementPosition(stmt);
814 817
815 // Keep the switch value on the stack until a case matches. 818 // Keep the switch value on the stack until a case matches.
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 break; 1442 break;
1440 } 1443 }
1441 // Fall through. 1444 // Fall through.
1442 case ObjectLiteral::Property::PROTOTYPE: 1445 case ObjectLiteral::Property::PROTOTYPE:
1443 // Duplicate receiver on stack. 1446 // Duplicate receiver on stack.
1444 __ ldr(r0, MemOperand(sp)); 1447 __ ldr(r0, MemOperand(sp));
1445 __ push(r0); 1448 __ push(r0);
1446 VisitForStackValue(key); 1449 VisitForStackValue(key);
1447 VisitForStackValue(value); 1450 VisitForStackValue(value);
1448 if (property->emit_store()) { 1451 if (property->emit_store()) {
1449 __ CallRuntime(Runtime::kSetProperty, 3); 1452 __ mov(r0, Operand(Smi::FromInt(NONE))); // PropertyAttributes
1453 __ push(r0);
1454 __ CallRuntime(Runtime::kSetProperty, 4);
1450 } else { 1455 } else {
1451 __ Drop(3); 1456 __ Drop(3);
1452 } 1457 }
1453 break; 1458 break;
1454 case ObjectLiteral::Property::GETTER: 1459 case ObjectLiteral::Property::GETTER:
1455 case ObjectLiteral::Property::SETTER: 1460 case ObjectLiteral::Property::SETTER:
1456 // Duplicate receiver on stack. 1461 // Duplicate receiver on stack.
1457 __ ldr(r0, MemOperand(sp)); 1462 __ ldr(r0, MemOperand(sp));
1458 __ push(r0); 1463 __ push(r0);
1459 VisitForStackValue(key); 1464 VisitForStackValue(key);
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
2033 EffectContext context(this); 2038 EffectContext context(this);
2034 EmitVariableAssignment(var, Token::ASSIGN); 2039 EmitVariableAssignment(var, Token::ASSIGN);
2035 break; 2040 break;
2036 } 2041 }
2037 case NAMED_PROPERTY: { 2042 case NAMED_PROPERTY: {
2038 __ push(r0); // Preserve value. 2043 __ push(r0); // Preserve value.
2039 VisitForAccumulatorValue(prop->obj()); 2044 VisitForAccumulatorValue(prop->obj());
2040 __ mov(r1, r0); 2045 __ mov(r1, r0);
2041 __ pop(r0); // Restore value. 2046 __ pop(r0); // Restore value.
2042 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 2047 __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
2043 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2048 Handle<Code> ic(Builtins::builtin(
2049 is_strict() ? Builtins::StoreIC_Initialize_Strict
2050 : Builtins::StoreIC_Initialize));
2044 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2051 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2045 break; 2052 break;
2046 } 2053 }
2047 case KEYED_PROPERTY: { 2054 case KEYED_PROPERTY: {
2048 __ push(r0); // Preserve value. 2055 __ push(r0); // Preserve value.
2049 if (prop->is_synthetic()) { 2056 if (prop->is_synthetic()) {
2050 ASSERT(prop->obj()->AsVariableProxy() != NULL); 2057 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2051 ASSERT(prop->key()->AsLiteral() != NULL); 2058 ASSERT(prop->key()->AsLiteral() != NULL);
2052 { AccumulatorValueContext for_object(this); 2059 { AccumulatorValueContext for_object(this);
2053 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); 2060 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
2054 } 2061 }
2055 __ mov(r2, r0); 2062 __ mov(r2, r0);
2056 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); 2063 __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
2057 } else { 2064 } else {
2058 VisitForStackValue(prop->obj()); 2065 VisitForStackValue(prop->obj());
2059 VisitForAccumulatorValue(prop->key()); 2066 VisitForAccumulatorValue(prop->key());
2060 __ mov(r1, r0); 2067 __ mov(r1, r0);
2061 __ pop(r2); 2068 __ pop(r2);
2062 } 2069 }
2063 __ pop(r0); // Restore value. 2070 __ pop(r0); // Restore value.
2064 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2071 Handle<Code> ic(Builtins::builtin(
2072 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
2073 : Builtins::KeyedStoreIC_Initialize));
2065 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2074 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2066 break; 2075 break;
2067 } 2076 }
2068 } 2077 }
2069 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 2078 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
2070 context()->Plug(r0); 2079 context()->Plug(r0);
2071 } 2080 }
2072 2081
2073 2082
2074 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2083 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2075 Token::Value op) { 2084 Token::Value op) {
2076 // Left-hand sides that rewrite to explicit property accesses do not reach 2085 // Left-hand sides that rewrite to explicit property accesses do not reach
2077 // here. 2086 // here.
2078 ASSERT(var != NULL); 2087 ASSERT(var != NULL);
2079 ASSERT(var->is_global() || var->AsSlot() != NULL); 2088 ASSERT(var->is_global() || var->AsSlot() != NULL);
2080 2089
2081 if (var->is_global()) { 2090 if (var->is_global()) {
2082 ASSERT(!var->is_this()); 2091 ASSERT(!var->is_this());
2083 // Assignment to a global variable. Use inline caching for the 2092 // Assignment to a global variable. Use inline caching for the
2084 // assignment. Right-hand-side value is passed in r0, variable name in 2093 // assignment. Right-hand-side value is passed in r0, variable name in
2085 // r2, and the global object in r1. 2094 // r2, and the global object in r1.
2086 __ mov(r2, Operand(var->name())); 2095 __ mov(r2, Operand(var->name()));
2087 __ ldr(r1, GlobalObjectOperand()); 2096 __ ldr(r1, GlobalObjectOperand());
2088 Handle<Code> ic(Builtins::builtin(is_strict() 2097 Handle<Code> ic(Builtins::builtin(
2089 ? Builtins::StoreIC_Initialize_Strict 2098 is_strict() ? Builtins::StoreIC_Initialize_Strict
2090 : Builtins::StoreIC_Initialize)); 2099 : Builtins::StoreIC_Initialize));
2091 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 2100 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2092 2101
2093 } else if (op == Token::INIT_CONST) { 2102 } else if (op == Token::INIT_CONST) {
2094 // Like var declarations, const declarations are hoisted to function 2103 // Like var declarations, const declarations are hoisted to function
2095 // scope. However, unlike var initializers, const initializers are able 2104 // scope. However, unlike var initializers, const initializers are able
2096 // to drill a hole to that function context, even from inside a 'with' 2105 // to drill a hole to that function context, even from inside a 'with'
2097 // context. We thus bypass the normal static scope lookup. 2106 // context. We thus bypass the normal static scope lookup.
2098 Slot* slot = var->AsSlot(); 2107 Slot* slot = var->AsSlot();
2099 Label skip; 2108 Label skip;
2100 switch (slot->type()) { 2109 switch (slot->type()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 // RecordWrite may destroy all its register arguments. 2158 // RecordWrite may destroy all its register arguments.
2150 __ mov(r3, result_register()); 2159 __ mov(r3, result_register());
2151 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2160 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
2152 __ RecordWrite(r1, Operand(offset), r2, r3); 2161 __ RecordWrite(r1, Operand(offset), r2, r3);
2153 break; 2162 break;
2154 } 2163 }
2155 2164
2156 case Slot::LOOKUP: 2165 case Slot::LOOKUP:
2157 // Call the runtime for the assignment. 2166 // Call the runtime for the assignment.
2158 __ push(r0); // Value. 2167 __ push(r0); // Value.
2159 __ mov(r0, Operand(slot->var()->name())); 2168 __ mov(r1, Operand(slot->var()->name()));
2160 __ Push(cp, r0); // Context and name. 2169 __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
2161 __ CallRuntime(Runtime::kStoreContextSlot, 3); 2170 __ Push(cp, r1, r0); // Context, name, strict mode.
2171 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2162 break; 2172 break;
2163 } 2173 }
2164 } 2174 }
2165 } 2175 }
2166 2176
2167 2177
2168 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2178 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2169 // Assignment to a property, using a named store IC. 2179 // Assignment to a property, using a named store IC.
2170 Property* prop = expr->target()->AsProperty(); 2180 Property* prop = expr->target()->AsProperty();
2171 ASSERT(prop != NULL); 2181 ASSERT(prop != NULL);
(...skipping 14 matching lines...) Expand all
2186 SetSourcePosition(expr->position()); 2196 SetSourcePosition(expr->position());
2187 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 2197 __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
2188 // Load receiver to r1. Leave a copy in the stack if needed for turning the 2198 // Load receiver to r1. Leave a copy in the stack if needed for turning the
2189 // receiver into fast case. 2199 // receiver into fast case.
2190 if (expr->ends_initialization_block()) { 2200 if (expr->ends_initialization_block()) {
2191 __ ldr(r1, MemOperand(sp)); 2201 __ ldr(r1, MemOperand(sp));
2192 } else { 2202 } else {
2193 __ pop(r1); 2203 __ pop(r1);
2194 } 2204 }
2195 2205
2196 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2206 Handle<Code> ic(Builtins::builtin(
2207 is_strict() ? Builtins::StoreIC_Initialize_Strict
2208 : Builtins::StoreIC_Initialize));
2197 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2209 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2198 2210
2199 // If the assignment ends an initialization block, revert to fast case. 2211 // If the assignment ends an initialization block, revert to fast case.
2200 if (expr->ends_initialization_block()) { 2212 if (expr->ends_initialization_block()) {
2201 __ push(r0); // Result of assignment, saved even if not needed. 2213 __ push(r0); // Result of assignment, saved even if not needed.
2202 // Receiver is under the result value. 2214 // Receiver is under the result value.
2203 __ ldr(ip, MemOperand(sp, kPointerSize)); 2215 __ ldr(ip, MemOperand(sp, kPointerSize));
2204 __ push(ip); 2216 __ push(ip);
2205 __ CallRuntime(Runtime::kToFastProperties, 1); 2217 __ CallRuntime(Runtime::kToFastProperties, 1);
2206 __ pop(r0); 2218 __ pop(r0);
(...skipping 23 matching lines...) Expand all
2230 SetSourcePosition(expr->position()); 2242 SetSourcePosition(expr->position());
2231 __ pop(r1); // Key. 2243 __ pop(r1); // Key.
2232 // Load receiver to r2. Leave a copy in the stack if needed for turning the 2244 // Load receiver to r2. Leave a copy in the stack if needed for turning the
2233 // receiver into fast case. 2245 // receiver into fast case.
2234 if (expr->ends_initialization_block()) { 2246 if (expr->ends_initialization_block()) {
2235 __ ldr(r2, MemOperand(sp)); 2247 __ ldr(r2, MemOperand(sp));
2236 } else { 2248 } else {
2237 __ pop(r2); 2249 __ pop(r2);
2238 } 2250 }
2239 2251
2240 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2252 Handle<Code> ic(Builtins::builtin(
2253 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
2254 : Builtins::KeyedStoreIC_Initialize));
2241 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2255 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2242 2256
2243 // If the assignment ends an initialization block, revert to fast case. 2257 // If the assignment ends an initialization block, revert to fast case.
2244 if (expr->ends_initialization_block()) { 2258 if (expr->ends_initialization_block()) {
2245 __ push(r0); // Result of assignment, saved even if not needed. 2259 __ push(r0); // Result of assignment, saved even if not needed.
2246 // Receiver is under the result value. 2260 // Receiver is under the result value.
2247 __ ldr(ip, MemOperand(sp, kPointerSize)); 2261 __ ldr(ip, MemOperand(sp, kPointerSize));
2248 __ push(ip); 2262 __ push(ip);
2249 __ CallRuntime(Runtime::kToFastProperties, 1); 2263 __ CallRuntime(Runtime::kToFastProperties, 1);
2250 __ pop(r0); 2264 __ pop(r0);
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after
3750 } else { 3764 } else {
3751 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3765 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3752 Token::ASSIGN); 3766 Token::ASSIGN);
3753 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3767 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3754 context()->Plug(r0); 3768 context()->Plug(r0);
3755 } 3769 }
3756 break; 3770 break;
3757 case NAMED_PROPERTY: { 3771 case NAMED_PROPERTY: {
3758 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 3772 __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
3759 __ pop(r1); 3773 __ pop(r1);
3760 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3774 Handle<Code> ic(Builtins::builtin(
3775 is_strict() ? Builtins::StoreIC_Initialize_Strict
3776 : Builtins::StoreIC_Initialize));
3761 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3777 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3762 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3778 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3763 if (expr->is_postfix()) { 3779 if (expr->is_postfix()) {
3764 if (!context()->IsEffect()) { 3780 if (!context()->IsEffect()) {
3765 context()->PlugTOS(); 3781 context()->PlugTOS();
3766 } 3782 }
3767 } else { 3783 } else {
3768 context()->Plug(r0); 3784 context()->Plug(r0);
3769 } 3785 }
3770 break; 3786 break;
3771 } 3787 }
3772 case KEYED_PROPERTY: { 3788 case KEYED_PROPERTY: {
3773 __ pop(r1); // Key. 3789 __ pop(r1); // Key.
3774 __ pop(r2); // Receiver. 3790 __ pop(r2); // Receiver.
3775 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3791 Handle<Code> ic(Builtins::builtin(
3792 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
3793 : Builtins::KeyedStoreIC_Initialize));
3776 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3794 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3777 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3795 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3778 if (expr->is_postfix()) { 3796 if (expr->is_postfix()) {
3779 if (!context()->IsEffect()) { 3797 if (!context()->IsEffect()) {
3780 context()->PlugTOS(); 3798 context()->PlugTOS();
3781 } 3799 }
3782 } else { 3800 } else {
3783 context()->Plug(r0); 3801 context()->Plug(r0);
3784 } 3802 }
3785 break; 3803 break;
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
4169 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 4187 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
4170 __ add(pc, r1, Operand(masm_->CodeObject())); 4188 __ add(pc, r1, Operand(masm_->CodeObject()));
4171 } 4189 }
4172 4190
4173 4191
4174 #undef __ 4192 #undef __
4175 4193
4176 } } // namespace v8::internal 4194 } } // namespace v8::internal
4177 4195
4178 #endif // V8_TARGET_ARCH_ARM 4196 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698