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 |