| 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 |