OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 139 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
140 | 140 |
141 #ifdef DEBUG | 141 #ifdef DEBUG |
142 if (strlen(FLAG_stop_at) > 0 && | 142 if (strlen(FLAG_stop_at) > 0 && |
143 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 143 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
144 __ Debug("stop-at", __LINE__, BREAK); | 144 __ Debug("stop-at", __LINE__, BREAK); |
145 } | 145 } |
146 #endif | 146 #endif |
147 | 147 |
148 // Classic mode functions and builtins need to replace the receiver with the | 148 // Sloppy mode functions and builtins need to replace the receiver with the |
149 // global proxy when called as functions (without an explicit receiver | 149 // global proxy when called as functions (without an explicit receiver |
150 // object). | 150 // object). |
151 if (info->is_classic_mode() && !info->is_native()) { | 151 if (info->is_sloppy_mode() && !info->is_native()) { |
152 Label ok; | 152 Label ok; |
153 int receiver_offset = info->scope()->num_parameters() * kXRegSizeInBytes; | 153 int receiver_offset = info->scope()->num_parameters() * kXRegSizeInBytes; |
154 __ Peek(x10, receiver_offset); | 154 __ Peek(x10, receiver_offset); |
155 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); | 155 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); |
156 | 156 |
157 __ Ldr(x10, GlobalObjectMemOperand()); | 157 __ Ldr(x10, GlobalObjectMemOperand()); |
158 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); | 158 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); |
159 __ Poke(x10, receiver_offset); | 159 __ Poke(x10, receiver_offset); |
160 | 160 |
161 __ Bind(&ok); | 161 __ Bind(&ok); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 int offset = num_parameters * kPointerSize; | 244 int offset = num_parameters * kPointerSize; |
245 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset); | 245 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset); |
246 __ Mov(x1, Operand(Smi::FromInt(num_parameters))); | 246 __ Mov(x1, Operand(Smi::FromInt(num_parameters))); |
247 __ Push(x3, x2, x1); | 247 __ Push(x3, x2, x1); |
248 | 248 |
249 // Arguments to ArgumentsAccessStub: | 249 // Arguments to ArgumentsAccessStub: |
250 // function, receiver address, parameter count. | 250 // function, receiver address, parameter count. |
251 // The stub will rewrite receiver and parameter count if the previous | 251 // The stub will rewrite receiver and parameter count if the previous |
252 // stack frame was an arguments adapter frame. | 252 // stack frame was an arguments adapter frame. |
253 ArgumentsAccessStub::Type type; | 253 ArgumentsAccessStub::Type type; |
254 if (!is_classic_mode()) { | 254 if (!is_sloppy_mode()) { |
255 type = ArgumentsAccessStub::NEW_STRICT; | 255 type = ArgumentsAccessStub::NEW_STRICT; |
256 } else if (function()->has_duplicate_parameters()) { | 256 } else if (function()->has_duplicate_parameters()) { |
257 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 257 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
258 } else { | 258 } else { |
259 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 259 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
260 } | 260 } |
261 ArgumentsAccessStub stub(type); | 261 ArgumentsAccessStub stub(type); |
262 __ CallStub(&stub); | 262 __ CallStub(&stub); |
263 | 263 |
264 SetVar(arguments, x0, x1, x2); | 264 SetVar(arguments, x0, x1, x2); |
265 } | 265 } |
266 | 266 |
267 if (FLAG_trace) { | 267 if (FLAG_trace) { |
268 __ CallRuntime(Runtime::kTraceEnter, 0); | 268 __ CallRuntime(Runtime::kTraceEnter, 0); |
269 } | 269 } |
(...skipping 1079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1349 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1349 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, |
1350 TypeofState typeof_state, | 1350 TypeofState typeof_state, |
1351 Label* slow) { | 1351 Label* slow) { |
1352 Register current = cp; | 1352 Register current = cp; |
1353 Register next = x10; | 1353 Register next = x10; |
1354 Register temp = x11; | 1354 Register temp = x11; |
1355 | 1355 |
1356 Scope* s = scope(); | 1356 Scope* s = scope(); |
1357 while (s != NULL) { | 1357 while (s != NULL) { |
1358 if (s->num_heap_slots() > 0) { | 1358 if (s->num_heap_slots() > 0) { |
1359 if (s->calls_non_strict_eval()) { | 1359 if (s->calls_sloppy_eval()) { |
1360 // Check that extension is NULL. | 1360 // Check that extension is NULL. |
1361 __ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); | 1361 __ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); |
1362 __ Cbnz(temp, slow); | 1362 __ Cbnz(temp, slow); |
1363 } | 1363 } |
1364 // Load next context in chain. | 1364 // Load next context in chain. |
1365 __ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); | 1365 __ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); |
1366 // Walk the rest of the chain without clobbering cp. | 1366 // Walk the rest of the chain without clobbering cp. |
1367 current = next; | 1367 current = next; |
1368 } | 1368 } |
1369 // If no outer scope calls eval, we do not need to check more | 1369 // If no outer scope calls eval, we do not need to check more |
1370 // context extensions. | 1370 // context extensions. |
1371 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 1371 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; |
1372 s = s->outer_scope(); | 1372 s = s->outer_scope(); |
1373 } | 1373 } |
1374 | 1374 |
1375 if (s->is_eval_scope()) { | 1375 if (s->is_eval_scope()) { |
1376 Label loop, fast; | 1376 Label loop, fast; |
1377 __ Mov(next, current); | 1377 __ Mov(next, current); |
1378 | 1378 |
1379 __ Bind(&loop); | 1379 __ Bind(&loop); |
1380 // Terminate at native context. | 1380 // Terminate at native context. |
1381 __ Ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); | 1381 __ Ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); |
(...skipping 17 matching lines...) Expand all Loading... |
1399 | 1399 |
1400 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1400 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1401 Label* slow) { | 1401 Label* slow) { |
1402 ASSERT(var->IsContextSlot()); | 1402 ASSERT(var->IsContextSlot()); |
1403 Register context = cp; | 1403 Register context = cp; |
1404 Register next = x10; | 1404 Register next = x10; |
1405 Register temp = x11; | 1405 Register temp = x11; |
1406 | 1406 |
1407 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1407 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
1408 if (s->num_heap_slots() > 0) { | 1408 if (s->num_heap_slots() > 0) { |
1409 if (s->calls_non_strict_eval()) { | 1409 if (s->calls_sloppy_eval()) { |
1410 // Check that extension is NULL. | 1410 // Check that extension is NULL. |
1411 __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); | 1411 __ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX)); |
1412 __ Cbnz(temp, slow); | 1412 __ Cbnz(temp, slow); |
1413 } | 1413 } |
1414 __ Ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); | 1414 __ Ldr(next, ContextMemOperand(context, Context::PREVIOUS_INDEX)); |
1415 // Walk the rest of the chain without clobbering cp. | 1415 // Walk the rest of the chain without clobbering cp. |
1416 context = next; | 1416 context = next; |
1417 } | 1417 } |
1418 } | 1418 } |
1419 // Check that last extension is NULL. | 1419 // Check that last extension is NULL. |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2137 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); | 2137 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); |
2138 CallStoreIC(); | 2138 CallStoreIC(); |
2139 break; | 2139 break; |
2140 } | 2140 } |
2141 case KEYED_PROPERTY: { | 2141 case KEYED_PROPERTY: { |
2142 __ Push(x0); // Preserve value. | 2142 __ Push(x0); // Preserve value. |
2143 VisitForStackValue(prop->obj()); | 2143 VisitForStackValue(prop->obj()); |
2144 VisitForAccumulatorValue(prop->key()); | 2144 VisitForAccumulatorValue(prop->key()); |
2145 __ Mov(x1, x0); | 2145 __ Mov(x1, x0); |
2146 __ Pop(x2, x0); | 2146 __ Pop(x2, x0); |
2147 Handle<Code> ic = is_classic_mode() | 2147 Handle<Code> ic = is_sloppy_mode() |
2148 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2148 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2149 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2149 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2150 CallIC(ic); | 2150 CallIC(ic); |
2151 break; | 2151 break; |
2152 } | 2152 } |
2153 } | 2153 } |
2154 context()->Plug(x0); | 2154 context()->Plug(x0); |
2155 } | 2155 } |
2156 | 2156 |
2157 | 2157 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2267 | 2267 |
2268 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2268 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2269 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); | 2269 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); |
2270 // Assignment to a property, using a keyed store IC. | 2270 // Assignment to a property, using a keyed store IC. |
2271 | 2271 |
2272 // Record source code position before IC call. | 2272 // Record source code position before IC call. |
2273 SetSourcePosition(expr->position()); | 2273 SetSourcePosition(expr->position()); |
2274 // TODO(all): Could we pass this in registers rather than on the stack? | 2274 // TODO(all): Could we pass this in registers rather than on the stack? |
2275 __ Pop(x1, x2); // Key and object holding the property. | 2275 __ Pop(x1, x2); // Key and object holding the property. |
2276 | 2276 |
2277 Handle<Code> ic = is_classic_mode() | 2277 Handle<Code> ic = is_sloppy_mode() |
2278 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2278 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2279 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2279 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2280 CallIC(ic, expr->AssignmentFeedbackId()); | 2280 CallIC(ic, expr->AssignmentFeedbackId()); |
2281 | 2281 |
2282 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2282 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2283 context()->Plug(x0); | 2283 context()->Plug(x0); |
2284 } | 2284 } |
2285 | 2285 |
2286 | 2286 |
2287 void FullCodeGenerator::VisitProperty(Property* expr) { | 2287 void FullCodeGenerator::VisitProperty(Property* expr) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2321 int arg_count = args->length(); | 2321 int arg_count = args->length(); |
2322 | 2322 |
2323 CallFunctionFlags flags; | 2323 CallFunctionFlags flags; |
2324 // Get the target function. | 2324 // Get the target function. |
2325 if (callee->IsVariableProxy()) { | 2325 if (callee->IsVariableProxy()) { |
2326 { StackValueContext context(this); | 2326 { StackValueContext context(this); |
2327 EmitVariableLoad(callee->AsVariableProxy()); | 2327 EmitVariableLoad(callee->AsVariableProxy()); |
2328 PrepareForBailout(callee, NO_REGISTERS); | 2328 PrepareForBailout(callee, NO_REGISTERS); |
2329 } | 2329 } |
2330 // Push undefined as receiver. This is patched in the method prologue if it | 2330 // Push undefined as receiver. This is patched in the method prologue if it |
2331 // is a classic mode method. | 2331 // is a sloppy mode method. |
2332 __ Push(isolate()->factory()->undefined_value()); | 2332 __ Push(isolate()->factory()->undefined_value()); |
2333 flags = NO_CALL_FUNCTION_FLAGS; | 2333 flags = NO_CALL_FUNCTION_FLAGS; |
2334 } else { | 2334 } else { |
2335 // Load the function from the receiver. | 2335 // Load the function from the receiver. |
2336 ASSERT(callee->IsProperty()); | 2336 ASSERT(callee->IsProperty()); |
2337 __ Peek(x0, 0); | 2337 __ Peek(x0, 0); |
2338 EmitNamedPropertyLoad(callee->AsProperty()); | 2338 EmitNamedPropertyLoad(callee->AsProperty()); |
2339 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2339 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2340 // Push the target function under the receiver. | 2340 // Push the target function under the receiver. |
2341 __ Pop(x10); | 2341 __ Pop(x10); |
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3885 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 3885 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
3886 switch (expr->op()) { | 3886 switch (expr->op()) { |
3887 case Token::DELETE: { | 3887 case Token::DELETE: { |
3888 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 3888 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
3889 Property* property = expr->expression()->AsProperty(); | 3889 Property* property = expr->expression()->AsProperty(); |
3890 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 3890 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
3891 | 3891 |
3892 if (property != NULL) { | 3892 if (property != NULL) { |
3893 VisitForStackValue(property->obj()); | 3893 VisitForStackValue(property->obj()); |
3894 VisitForStackValue(property->key()); | 3894 VisitForStackValue(property->key()); |
3895 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) | 3895 StrictModeFlag strict_mode_flag = (language_mode() == SLOPPY_MODE) |
3896 ? kNonStrictMode : kStrictMode; | 3896 ? kSloppyMode : kStrictMode; |
3897 __ Mov(x10, Operand(Smi::FromInt(strict_mode_flag))); | 3897 __ Mov(x10, Operand(Smi::FromInt(strict_mode_flag))); |
3898 __ Push(x10); | 3898 __ Push(x10); |
3899 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3899 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3900 context()->Plug(x0); | 3900 context()->Plug(x0); |
3901 } else if (proxy != NULL) { | 3901 } else if (proxy != NULL) { |
3902 Variable* var = proxy->var(); | 3902 Variable* var = proxy->var(); |
3903 // Delete of an unqualified identifier is disallowed in strict mode | 3903 // Delete of an unqualified identifier is disallowed in strict mode |
3904 // but "delete this" is allowed. | 3904 // but "delete this" is allowed. |
3905 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); | 3905 ASSERT(language_mode() == SLOPPY_MODE || var->is_this()); |
3906 if (var->IsUnallocated()) { | 3906 if (var->IsUnallocated()) { |
3907 __ Ldr(x12, GlobalObjectMemOperand()); | 3907 __ Ldr(x12, GlobalObjectMemOperand()); |
3908 __ Mov(x11, Operand(var->name())); | 3908 __ Mov(x11, Operand(var->name())); |
3909 __ Mov(x10, Operand(Smi::FromInt(kNonStrictMode))); | 3909 __ Mov(x10, Operand(Smi::FromInt(kSloppyMode))); |
3910 __ Push(x12, x11, x10); | 3910 __ Push(x12, x11, x10); |
3911 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3911 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3912 context()->Plug(x0); | 3912 context()->Plug(x0); |
3913 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3913 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
3914 // Result of deleting non-global, non-dynamic variables is false. | 3914 // Result of deleting non-global, non-dynamic variables is false. |
3915 // The subexpression does not have side effects. | 3915 // The subexpression does not have side effects. |
3916 context()->Plug(var->is_this()); | 3916 context()->Plug(var->is_this()); |
3917 } else { | 3917 } else { |
3918 // Non-global variable. Call the runtime to try to delete from the | 3918 // Non-global variable. Call the runtime to try to delete from the |
3919 // context where the variable was introduced. | 3919 // context where the variable was introduced. |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4156 context()->PlugTOS(); | 4156 context()->PlugTOS(); |
4157 } | 4157 } |
4158 } else { | 4158 } else { |
4159 context()->Plug(x0); | 4159 context()->Plug(x0); |
4160 } | 4160 } |
4161 break; | 4161 break; |
4162 } | 4162 } |
4163 case KEYED_PROPERTY: { | 4163 case KEYED_PROPERTY: { |
4164 __ Pop(x1); // Key. | 4164 __ Pop(x1); // Key. |
4165 __ Pop(x2); // Receiver. | 4165 __ Pop(x2); // Receiver. |
4166 Handle<Code> ic = is_classic_mode() | 4166 Handle<Code> ic = is_sloppy_mode() |
4167 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4167 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4168 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4168 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4169 CallIC(ic, expr->CountStoreFeedbackId()); | 4169 CallIC(ic, expr->CountStoreFeedbackId()); |
4170 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4170 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4171 if (expr->is_postfix()) { | 4171 if (expr->is_postfix()) { |
4172 if (!context()->IsEffect()) { | 4172 if (!context()->IsEffect()) { |
4173 context()->PlugTOS(); | 4173 context()->PlugTOS(); |
4174 } | 4174 } |
4175 } else { | 4175 } else { |
4176 context()->Plug(x0); | 4176 context()->Plug(x0); |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4984 return previous_; | 4984 return previous_; |
4985 } | 4985 } |
4986 | 4986 |
4987 | 4987 |
4988 #undef __ | 4988 #undef __ |
4989 | 4989 |
4990 | 4990 |
4991 } } // namespace v8::internal | 4991 } } // namespace v8::internal |
4992 | 4992 |
4993 #endif // V8_TARGET_ARCH_A64 | 4993 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |