OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |