| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 | 128 |
| 129 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 129 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 130 | 130 |
| 131 #ifdef DEBUG | 131 #ifdef DEBUG |
| 132 if (strlen(FLAG_stop_at) > 0 && | 132 if (strlen(FLAG_stop_at) > 0 && |
| 133 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 133 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 134 __ int3(); | 134 __ int3(); |
| 135 } | 135 } |
| 136 #endif | 136 #endif |
| 137 | 137 |
| 138 // Classic mode functions and builtins need to replace the receiver with the | 138 // Sloppy mode functions and builtins need to replace the receiver with the |
| 139 // global proxy when called as functions (without an explicit receiver | 139 // global proxy when called as functions (without an explicit receiver |
| 140 // object). | 140 // object). |
| 141 if (info->is_classic_mode() && !info->is_native()) { | 141 if (info->is_sloppy_mode() && !info->is_native()) { |
| 142 Label ok; | 142 Label ok; |
| 143 // +1 for return address. | 143 // +1 for return address. |
| 144 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); | 144 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); |
| 145 __ movp(rcx, args.GetReceiverOperand()); | 145 __ movp(rcx, args.GetReceiverOperand()); |
| 146 | 146 |
| 147 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); | 147 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 148 __ j(not_equal, &ok, Label::kNear); | 148 __ j(not_equal, &ok, Label::kNear); |
| 149 | 149 |
| 150 __ movp(rcx, GlobalObjectOperand()); | 150 __ movp(rcx, GlobalObjectOperand()); |
| 151 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 151 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 int offset = num_parameters * kPointerSize; | 237 int offset = num_parameters * kPointerSize; |
| 238 __ lea(rdx, | 238 __ lea(rdx, |
| 239 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); | 239 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); |
| 240 __ push(rdx); | 240 __ push(rdx); |
| 241 __ Push(Smi::FromInt(num_parameters)); | 241 __ Push(Smi::FromInt(num_parameters)); |
| 242 // Arguments to ArgumentsAccessStub: | 242 // Arguments to ArgumentsAccessStub: |
| 243 // function, receiver address, parameter count. | 243 // function, receiver address, parameter count. |
| 244 // The stub will rewrite receiver and parameter count if the previous | 244 // The stub will rewrite receiver and parameter count if the previous |
| 245 // stack frame was an arguments adapter frame. | 245 // stack frame was an arguments adapter frame. |
| 246 ArgumentsAccessStub::Type type; | 246 ArgumentsAccessStub::Type type; |
| 247 if (!is_classic_mode()) { | 247 if (!is_sloppy_mode()) { |
| 248 type = ArgumentsAccessStub::NEW_STRICT; | 248 type = ArgumentsAccessStub::NEW_STRICT; |
| 249 } else if (function()->has_duplicate_parameters()) { | 249 } else if (function()->has_duplicate_parameters()) { |
| 250 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 250 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
| 251 } else { | 251 } else { |
| 252 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 252 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
| 253 } | 253 } |
| 254 ArgumentsAccessStub stub(type); | 254 ArgumentsAccessStub stub(type); |
| 255 __ CallStub(&stub); | 255 __ CallStub(&stub); |
| 256 | 256 |
| 257 SetVar(arguments, rax, rbx, rdx); | 257 SetVar(arguments, rax, rbx, rdx); |
| 258 } | 258 } |
| 259 | 259 |
| 260 if (FLAG_trace) { | 260 if (FLAG_trace) { |
| 261 __ CallRuntime(Runtime::kTraceEnter, 0); | 261 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 262 } | 262 } |
| (...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1315 | 1315 |
| 1316 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1316 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, |
| 1317 TypeofState typeof_state, | 1317 TypeofState typeof_state, |
| 1318 Label* slow) { | 1318 Label* slow) { |
| 1319 Register context = rsi; | 1319 Register context = rsi; |
| 1320 Register temp = rdx; | 1320 Register temp = rdx; |
| 1321 | 1321 |
| 1322 Scope* s = scope(); | 1322 Scope* s = scope(); |
| 1323 while (s != NULL) { | 1323 while (s != NULL) { |
| 1324 if (s->num_heap_slots() > 0) { | 1324 if (s->num_heap_slots() > 0) { |
| 1325 if (s->calls_non_strict_eval()) { | 1325 if (s->calls_sloppy_eval()) { |
| 1326 // Check that extension is NULL. | 1326 // Check that extension is NULL. |
| 1327 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 1327 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), |
| 1328 Immediate(0)); | 1328 Immediate(0)); |
| 1329 __ j(not_equal, slow); | 1329 __ j(not_equal, slow); |
| 1330 } | 1330 } |
| 1331 // Load next context in chain. | 1331 // Load next context in chain. |
| 1332 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1332 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); |
| 1333 // Walk the rest of the chain without clobbering rsi. | 1333 // Walk the rest of the chain without clobbering rsi. |
| 1334 context = temp; | 1334 context = temp; |
| 1335 } | 1335 } |
| 1336 // If no outer scope calls eval, we do not need to check more | 1336 // If no outer scope calls eval, we do not need to check more |
| 1337 // context extensions. If we have reached an eval scope, we check | 1337 // context extensions. If we have reached an eval scope, we check |
| 1338 // all extensions from this point. | 1338 // all extensions from this point. |
| 1339 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 1339 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; |
| 1340 s = s->outer_scope(); | 1340 s = s->outer_scope(); |
| 1341 } | 1341 } |
| 1342 | 1342 |
| 1343 if (s != NULL && s->is_eval_scope()) { | 1343 if (s != NULL && s->is_eval_scope()) { |
| 1344 // Loop up the context chain. There is no frame effect so it is | 1344 // Loop up the context chain. There is no frame effect so it is |
| 1345 // safe to use raw labels here. | 1345 // safe to use raw labels here. |
| 1346 Label next, fast; | 1346 Label next, fast; |
| 1347 if (!context.is(temp)) { | 1347 if (!context.is(temp)) { |
| 1348 __ movp(temp, context); | 1348 __ movp(temp, context); |
| 1349 } | 1349 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1374 | 1374 |
| 1375 | 1375 |
| 1376 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1376 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1377 Label* slow) { | 1377 Label* slow) { |
| 1378 ASSERT(var->IsContextSlot()); | 1378 ASSERT(var->IsContextSlot()); |
| 1379 Register context = rsi; | 1379 Register context = rsi; |
| 1380 Register temp = rbx; | 1380 Register temp = rbx; |
| 1381 | 1381 |
| 1382 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1382 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| 1383 if (s->num_heap_slots() > 0) { | 1383 if (s->num_heap_slots() > 0) { |
| 1384 if (s->calls_non_strict_eval()) { | 1384 if (s->calls_sloppy_eval()) { |
| 1385 // Check that extension is NULL. | 1385 // Check that extension is NULL. |
| 1386 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), | 1386 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), |
| 1387 Immediate(0)); | 1387 Immediate(0)); |
| 1388 __ j(not_equal, slow); | 1388 __ j(not_equal, slow); |
| 1389 } | 1389 } |
| 1390 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1390 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); |
| 1391 // Walk the rest of the chain without clobbering rsi. | 1391 // Walk the rest of the chain without clobbering rsi. |
| 1392 context = temp; | 1392 context = temp; |
| 1393 } | 1393 } |
| 1394 } | 1394 } |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2382 CallStoreIC(); | 2382 CallStoreIC(); |
| 2383 break; | 2383 break; |
| 2384 } | 2384 } |
| 2385 case KEYED_PROPERTY: { | 2385 case KEYED_PROPERTY: { |
| 2386 __ push(rax); // Preserve value. | 2386 __ push(rax); // Preserve value. |
| 2387 VisitForStackValue(prop->obj()); | 2387 VisitForStackValue(prop->obj()); |
| 2388 VisitForAccumulatorValue(prop->key()); | 2388 VisitForAccumulatorValue(prop->key()); |
| 2389 __ movp(rcx, rax); | 2389 __ movp(rcx, rax); |
| 2390 __ pop(rdx); | 2390 __ pop(rdx); |
| 2391 __ pop(rax); // Restore value. | 2391 __ pop(rax); // Restore value. |
| 2392 Handle<Code> ic = is_classic_mode() | 2392 Handle<Code> ic = is_sloppy_mode() |
| 2393 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2393 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2394 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2394 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2395 CallIC(ic); | 2395 CallIC(ic); |
| 2396 break; | 2396 break; |
| 2397 } | 2397 } |
| 2398 } | 2398 } |
| 2399 context()->Plug(rax); | 2399 context()->Plug(rax); |
| 2400 } | 2400 } |
| 2401 | 2401 |
| 2402 | 2402 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 } | 2503 } |
| 2504 | 2504 |
| 2505 | 2505 |
| 2506 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2506 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2507 // Assignment to a property, using a keyed store IC. | 2507 // Assignment to a property, using a keyed store IC. |
| 2508 | 2508 |
| 2509 __ pop(rcx); | 2509 __ pop(rcx); |
| 2510 __ pop(rdx); | 2510 __ pop(rdx); |
| 2511 // Record source code position before IC call. | 2511 // Record source code position before IC call. |
| 2512 SetSourcePosition(expr->position()); | 2512 SetSourcePosition(expr->position()); |
| 2513 Handle<Code> ic = is_classic_mode() | 2513 Handle<Code> ic = is_sloppy_mode() |
| 2514 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2514 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2515 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2515 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2516 CallIC(ic, expr->AssignmentFeedbackId()); | 2516 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2517 | 2517 |
| 2518 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2518 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2519 context()->Plug(rax); | 2519 context()->Plug(rax); |
| 2520 } | 2520 } |
| 2521 | 2521 |
| 2522 | 2522 |
| 2523 void FullCodeGenerator::VisitProperty(Property* expr) { | 2523 void FullCodeGenerator::VisitProperty(Property* expr) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2553 int arg_count = args->length(); | 2553 int arg_count = args->length(); |
| 2554 | 2554 |
| 2555 CallFunctionFlags flags; | 2555 CallFunctionFlags flags; |
| 2556 // Get the target function; | 2556 // Get the target function; |
| 2557 if (callee->IsVariableProxy()) { | 2557 if (callee->IsVariableProxy()) { |
| 2558 { StackValueContext context(this); | 2558 { StackValueContext context(this); |
| 2559 EmitVariableLoad(callee->AsVariableProxy()); | 2559 EmitVariableLoad(callee->AsVariableProxy()); |
| 2560 PrepareForBailout(callee, NO_REGISTERS); | 2560 PrepareForBailout(callee, NO_REGISTERS); |
| 2561 } | 2561 } |
| 2562 // Push undefined as receiver. This is patched in the method prologue if it | 2562 // Push undefined as receiver. This is patched in the method prologue if it |
| 2563 // is a classic mode method. | 2563 // is a sloppy mode method. |
| 2564 __ Push(isolate()->factory()->undefined_value()); | 2564 __ Push(isolate()->factory()->undefined_value()); |
| 2565 flags = NO_CALL_FUNCTION_FLAGS; | 2565 flags = NO_CALL_FUNCTION_FLAGS; |
| 2566 } else { | 2566 } else { |
| 2567 // Load the function from the receiver. | 2567 // Load the function from the receiver. |
| 2568 ASSERT(callee->IsProperty()); | 2568 ASSERT(callee->IsProperty()); |
| 2569 __ movp(rax, Operand(rsp, 0)); | 2569 __ movp(rax, Operand(rsp, 0)); |
| 2570 EmitNamedPropertyLoad(callee->AsProperty()); | 2570 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2571 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2571 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2572 // Push the target function under the receiver. | 2572 // Push the target function under the receiver. |
| 2573 __ push(Operand(rsp, 0)); | 2573 __ push(Operand(rsp, 0)); |
| (...skipping 1599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4173 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4173 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4174 switch (expr->op()) { | 4174 switch (expr->op()) { |
| 4175 case Token::DELETE: { | 4175 case Token::DELETE: { |
| 4176 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4176 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4177 Property* property = expr->expression()->AsProperty(); | 4177 Property* property = expr->expression()->AsProperty(); |
| 4178 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4178 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4179 | 4179 |
| 4180 if (property != NULL) { | 4180 if (property != NULL) { |
| 4181 VisitForStackValue(property->obj()); | 4181 VisitForStackValue(property->obj()); |
| 4182 VisitForStackValue(property->key()); | 4182 VisitForStackValue(property->key()); |
| 4183 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) | 4183 StrictModeFlag strict_mode_flag = (language_mode() == SLOPPY_MODE) |
| 4184 ? kNonStrictMode : kStrictMode; | 4184 ? kSloppyMode : kStrictMode; |
| 4185 __ Push(Smi::FromInt(strict_mode_flag)); | 4185 __ Push(Smi::FromInt(strict_mode_flag)); |
| 4186 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4186 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4187 context()->Plug(rax); | 4187 context()->Plug(rax); |
| 4188 } else if (proxy != NULL) { | 4188 } else if (proxy != NULL) { |
| 4189 Variable* var = proxy->var(); | 4189 Variable* var = proxy->var(); |
| 4190 // Delete of an unqualified identifier is disallowed in strict mode | 4190 // Delete of an unqualified identifier is disallowed in strict mode |
| 4191 // but "delete this" is allowed. | 4191 // but "delete this" is allowed. |
| 4192 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); | 4192 ASSERT(language_mode() == SLOPPY_MODE || var->is_this()); |
| 4193 if (var->IsUnallocated()) { | 4193 if (var->IsUnallocated()) { |
| 4194 __ push(GlobalObjectOperand()); | 4194 __ push(GlobalObjectOperand()); |
| 4195 __ Push(var->name()); | 4195 __ Push(var->name()); |
| 4196 __ Push(Smi::FromInt(kNonStrictMode)); | 4196 __ Push(Smi::FromInt(kSloppyMode)); |
| 4197 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4197 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4198 context()->Plug(rax); | 4198 context()->Plug(rax); |
| 4199 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4199 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4200 // Result of deleting non-global variables is false. 'this' is | 4200 // Result of deleting non-global variables is false. 'this' is |
| 4201 // not really a variable, though we implement it as one. The | 4201 // not really a variable, though we implement it as one. The |
| 4202 // subexpression does not have side effects. | 4202 // subexpression does not have side effects. |
| 4203 context()->Plug(var->is_this()); | 4203 context()->Plug(var->is_this()); |
| 4204 } else { | 4204 } else { |
| 4205 // Non-global variable. Call the runtime to try to delete from the | 4205 // Non-global variable. Call the runtime to try to delete from the |
| 4206 // context where the variable was introduced. | 4206 // context where the variable was introduced. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4448 context()->PlugTOS(); | 4448 context()->PlugTOS(); |
| 4449 } | 4449 } |
| 4450 } else { | 4450 } else { |
| 4451 context()->Plug(rax); | 4451 context()->Plug(rax); |
| 4452 } | 4452 } |
| 4453 break; | 4453 break; |
| 4454 } | 4454 } |
| 4455 case KEYED_PROPERTY: { | 4455 case KEYED_PROPERTY: { |
| 4456 __ pop(rcx); | 4456 __ pop(rcx); |
| 4457 __ pop(rdx); | 4457 __ pop(rdx); |
| 4458 Handle<Code> ic = is_classic_mode() | 4458 Handle<Code> ic = is_sloppy_mode() |
| 4459 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4459 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4460 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4460 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4461 CallIC(ic, expr->CountStoreFeedbackId()); | 4461 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4462 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4462 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4463 if (expr->is_postfix()) { | 4463 if (expr->is_postfix()) { |
| 4464 if (!context()->IsEffect()) { | 4464 if (!context()->IsEffect()) { |
| 4465 context()->PlugTOS(); | 4465 context()->PlugTOS(); |
| 4466 } | 4466 } |
| 4467 } else { | 4467 } else { |
| 4468 context()->Plug(rax); | 4468 context()->Plug(rax); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4907 | 4907 |
| 4908 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4908 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4909 Assembler::target_address_at(call_target_address)); | 4909 Assembler::target_address_at(call_target_address)); |
| 4910 return OSR_AFTER_STACK_CHECK; | 4910 return OSR_AFTER_STACK_CHECK; |
| 4911 } | 4911 } |
| 4912 | 4912 |
| 4913 | 4913 |
| 4914 } } // namespace v8::internal | 4914 } } // namespace v8::internal |
| 4915 | 4915 |
| 4916 #endif // V8_TARGET_ARCH_X64 | 4916 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |