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 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; | 144 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; |
145 __ mov(ecx, Operand(esp, receiver_offset)); | 145 __ mov(ecx, Operand(esp, receiver_offset)); |
146 | 146 |
147 __ cmp(ecx, isolate()->factory()->undefined_value()); | 147 __ cmp(ecx, isolate()->factory()->undefined_value()); |
148 __ j(not_equal, &ok, Label::kNear); | 148 __ j(not_equal, &ok, Label::kNear); |
149 | 149 |
150 __ mov(ecx, GlobalObjectOperand()); | 150 __ mov(ecx, GlobalObjectOperand()); |
151 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 151 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 int offset = num_parameters * kPointerSize; | 238 int offset = num_parameters * kPointerSize; |
239 __ lea(edx, | 239 __ lea(edx, |
240 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); | 240 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); |
241 __ push(edx); | 241 __ push(edx); |
242 __ push(Immediate(Smi::FromInt(num_parameters))); | 242 __ push(Immediate(Smi::FromInt(num_parameters))); |
243 // Arguments to ArgumentsAccessStub: | 243 // Arguments to ArgumentsAccessStub: |
244 // function, receiver address, parameter count. | 244 // function, receiver address, parameter count. |
245 // The stub will rewrite receiver and parameter count if the previous | 245 // The stub will rewrite receiver and parameter count if the previous |
246 // stack frame was an arguments adapter frame. | 246 // stack frame was an arguments adapter frame. |
247 ArgumentsAccessStub::Type type; | 247 ArgumentsAccessStub::Type type; |
248 if (!is_classic_mode()) { | 248 if (!is_sloppy_mode()) { |
249 type = ArgumentsAccessStub::NEW_STRICT; | 249 type = ArgumentsAccessStub::NEW_STRICT; |
250 } else if (function()->has_duplicate_parameters()) { | 250 } else if (function()->has_duplicate_parameters()) { |
251 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 251 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
252 } else { | 252 } else { |
253 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 253 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
254 } | 254 } |
255 ArgumentsAccessStub stub(type); | 255 ArgumentsAccessStub stub(type); |
256 __ CallStub(&stub); | 256 __ CallStub(&stub); |
257 | 257 |
258 SetVar(arguments, eax, ebx, edx); | 258 SetVar(arguments, eax, ebx, edx); |
259 } | 259 } |
260 | 260 |
261 if (FLAG_trace) { | 261 if (FLAG_trace) { |
262 __ CallRuntime(Runtime::kTraceEnter, 0); | 262 __ CallRuntime(Runtime::kTraceEnter, 0); |
263 } | 263 } |
(...skipping 1026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 | 1290 |
1291 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1291 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, |
1292 TypeofState typeof_state, | 1292 TypeofState typeof_state, |
1293 Label* slow) { | 1293 Label* slow) { |
1294 Register context = esi; | 1294 Register context = esi; |
1295 Register temp = edx; | 1295 Register temp = edx; |
1296 | 1296 |
1297 Scope* s = scope(); | 1297 Scope* s = scope(); |
1298 while (s != NULL) { | 1298 while (s != NULL) { |
1299 if (s->num_heap_slots() > 0) { | 1299 if (s->num_heap_slots() > 0) { |
1300 if (s->calls_non_strict_eval()) { | 1300 if (s->calls_sloppy_eval()) { |
1301 // Check that extension is NULL. | 1301 // Check that extension is NULL. |
1302 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), | 1302 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), |
1303 Immediate(0)); | 1303 Immediate(0)); |
1304 __ j(not_equal, slow); | 1304 __ j(not_equal, slow); |
1305 } | 1305 } |
1306 // Load next context in chain. | 1306 // Load next context in chain. |
1307 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1307 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); |
1308 // Walk the rest of the chain without clobbering esi. | 1308 // Walk the rest of the chain without clobbering esi. |
1309 context = temp; | 1309 context = temp; |
1310 } | 1310 } |
1311 // If no outer scope calls eval, we do not need to check more | 1311 // If no outer scope calls eval, we do not need to check more |
1312 // context extensions. If we have reached an eval scope, we check | 1312 // context extensions. If we have reached an eval scope, we check |
1313 // all extensions from this point. | 1313 // all extensions from this point. |
1314 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 1314 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; |
1315 s = s->outer_scope(); | 1315 s = s->outer_scope(); |
1316 } | 1316 } |
1317 | 1317 |
1318 if (s != NULL && s->is_eval_scope()) { | 1318 if (s != NULL && s->is_eval_scope()) { |
1319 // Loop up the context chain. There is no frame effect so it is | 1319 // Loop up the context chain. There is no frame effect so it is |
1320 // safe to use raw labels here. | 1320 // safe to use raw labels here. |
1321 Label next, fast; | 1321 Label next, fast; |
1322 if (!context.is(temp)) { | 1322 if (!context.is(temp)) { |
1323 __ mov(temp, context); | 1323 __ mov(temp, context); |
1324 } | 1324 } |
(...skipping 24 matching lines...) Expand all Loading... |
1349 | 1349 |
1350 | 1350 |
1351 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1351 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1352 Label* slow) { | 1352 Label* slow) { |
1353 ASSERT(var->IsContextSlot()); | 1353 ASSERT(var->IsContextSlot()); |
1354 Register context = esi; | 1354 Register context = esi; |
1355 Register temp = ebx; | 1355 Register temp = ebx; |
1356 | 1356 |
1357 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1357 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
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 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), | 1361 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), |
1362 Immediate(0)); | 1362 Immediate(0)); |
1363 __ j(not_equal, slow); | 1363 __ j(not_equal, slow); |
1364 } | 1364 } |
1365 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1365 __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); |
1366 // Walk the rest of the chain without clobbering esi. | 1366 // Walk the rest of the chain without clobbering esi. |
1367 context = temp; | 1367 context = temp; |
1368 } | 1368 } |
1369 } | 1369 } |
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2390 CallStoreIC(); | 2390 CallStoreIC(); |
2391 break; | 2391 break; |
2392 } | 2392 } |
2393 case KEYED_PROPERTY: { | 2393 case KEYED_PROPERTY: { |
2394 __ push(eax); // Preserve value. | 2394 __ push(eax); // Preserve value. |
2395 VisitForStackValue(prop->obj()); | 2395 VisitForStackValue(prop->obj()); |
2396 VisitForAccumulatorValue(prop->key()); | 2396 VisitForAccumulatorValue(prop->key()); |
2397 __ mov(ecx, eax); | 2397 __ mov(ecx, eax); |
2398 __ pop(edx); // Receiver. | 2398 __ pop(edx); // Receiver. |
2399 __ pop(eax); // Restore value. | 2399 __ pop(eax); // Restore value. |
2400 Handle<Code> ic = is_classic_mode() | 2400 Handle<Code> ic = is_sloppy_mode() |
2401 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2401 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2402 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2402 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2403 CallIC(ic); | 2403 CallIC(ic); |
2404 break; | 2404 break; |
2405 } | 2405 } |
2406 } | 2406 } |
2407 context()->Plug(eax); | 2407 context()->Plug(eax); |
2408 } | 2408 } |
2409 | 2409 |
2410 | 2410 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2516 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2516 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2517 // Assignment to a property, using a keyed store IC. | 2517 // Assignment to a property, using a keyed store IC. |
2518 // eax : value | 2518 // eax : value |
2519 // esp[0] : key | 2519 // esp[0] : key |
2520 // esp[kPointerSize] : receiver | 2520 // esp[kPointerSize] : receiver |
2521 | 2521 |
2522 __ pop(ecx); // Key. | 2522 __ pop(ecx); // Key. |
2523 __ pop(edx); | 2523 __ pop(edx); |
2524 // Record source code position before IC call. | 2524 // Record source code position before IC call. |
2525 SetSourcePosition(expr->position()); | 2525 SetSourcePosition(expr->position()); |
2526 Handle<Code> ic = is_classic_mode() | 2526 Handle<Code> ic = is_sloppy_mode() |
2527 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2527 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2528 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2528 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2529 CallIC(ic, expr->AssignmentFeedbackId()); | 2529 CallIC(ic, expr->AssignmentFeedbackId()); |
2530 | 2530 |
2531 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2531 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2532 context()->Plug(eax); | 2532 context()->Plug(eax); |
2533 } | 2533 } |
2534 | 2534 |
2535 | 2535 |
2536 void FullCodeGenerator::VisitProperty(Property* expr) { | 2536 void FullCodeGenerator::VisitProperty(Property* expr) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2570 int arg_count = args->length(); | 2570 int arg_count = args->length(); |
2571 | 2571 |
2572 CallFunctionFlags flags; | 2572 CallFunctionFlags flags; |
2573 // Get the target function. | 2573 // Get the target function. |
2574 if (callee->IsVariableProxy()) { | 2574 if (callee->IsVariableProxy()) { |
2575 { StackValueContext context(this); | 2575 { StackValueContext context(this); |
2576 EmitVariableLoad(callee->AsVariableProxy()); | 2576 EmitVariableLoad(callee->AsVariableProxy()); |
2577 PrepareForBailout(callee, NO_REGISTERS); | 2577 PrepareForBailout(callee, NO_REGISTERS); |
2578 } | 2578 } |
2579 // Push undefined as receiver. This is patched in the method prologue if it | 2579 // Push undefined as receiver. This is patched in the method prologue if it |
2580 // is a classic mode method. | 2580 // is a sloppy mode method. |
2581 __ push(Immediate(isolate()->factory()->undefined_value())); | 2581 __ push(Immediate(isolate()->factory()->undefined_value())); |
2582 flags = NO_CALL_FUNCTION_FLAGS; | 2582 flags = NO_CALL_FUNCTION_FLAGS; |
2583 } else { | 2583 } else { |
2584 // Load the function from the receiver. | 2584 // Load the function from the receiver. |
2585 ASSERT(callee->IsProperty()); | 2585 ASSERT(callee->IsProperty()); |
2586 __ mov(edx, Operand(esp, 0)); | 2586 __ mov(edx, Operand(esp, 0)); |
2587 EmitNamedPropertyLoad(callee->AsProperty()); | 2587 EmitNamedPropertyLoad(callee->AsProperty()); |
2588 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2588 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2589 // Push the target function under the receiver. | 2589 // Push the target function under the receiver. |
2590 __ push(Operand(esp, 0)); | 2590 __ push(Operand(esp, 0)); |
(...skipping 1584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4175 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4175 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
4176 switch (expr->op()) { | 4176 switch (expr->op()) { |
4177 case Token::DELETE: { | 4177 case Token::DELETE: { |
4178 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4178 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4179 Property* property = expr->expression()->AsProperty(); | 4179 Property* property = expr->expression()->AsProperty(); |
4180 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4180 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4181 | 4181 |
4182 if (property != NULL) { | 4182 if (property != NULL) { |
4183 VisitForStackValue(property->obj()); | 4183 VisitForStackValue(property->obj()); |
4184 VisitForStackValue(property->key()); | 4184 VisitForStackValue(property->key()); |
4185 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) | 4185 StrictModeFlag strict_mode_flag = (language_mode() == SLOPPY_MODE) |
4186 ? kNonStrictMode : kStrictMode; | 4186 ? kSloppyMode : kStrictMode; |
4187 __ push(Immediate(Smi::FromInt(strict_mode_flag))); | 4187 __ push(Immediate(Smi::FromInt(strict_mode_flag))); |
4188 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4188 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4189 context()->Plug(eax); | 4189 context()->Plug(eax); |
4190 } else if (proxy != NULL) { | 4190 } else if (proxy != NULL) { |
4191 Variable* var = proxy->var(); | 4191 Variable* var = proxy->var(); |
4192 // Delete of an unqualified identifier is disallowed in strict mode | 4192 // Delete of an unqualified identifier is disallowed in strict mode |
4193 // but "delete this" is allowed. | 4193 // but "delete this" is allowed. |
4194 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); | 4194 ASSERT(language_mode() == SLOPPY_MODE || var->is_this()); |
4195 if (var->IsUnallocated()) { | 4195 if (var->IsUnallocated()) { |
4196 __ push(GlobalObjectOperand()); | 4196 __ push(GlobalObjectOperand()); |
4197 __ push(Immediate(var->name())); | 4197 __ push(Immediate(var->name())); |
4198 __ push(Immediate(Smi::FromInt(kNonStrictMode))); | 4198 __ push(Immediate(Smi::FromInt(kSloppyMode))); |
4199 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4199 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4200 context()->Plug(eax); | 4200 context()->Plug(eax); |
4201 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4201 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4202 // Result of deleting non-global variables is false. 'this' is | 4202 // Result of deleting non-global variables is false. 'this' is |
4203 // not really a variable, though we implement it as one. The | 4203 // not really a variable, though we implement it as one. The |
4204 // subexpression does not have side effects. | 4204 // subexpression does not have side effects. |
4205 context()->Plug(var->is_this()); | 4205 context()->Plug(var->is_this()); |
4206 } else { | 4206 } else { |
4207 // Non-global variable. Call the runtime to try to delete from the | 4207 // Non-global variable. Call the runtime to try to delete from the |
4208 // context where the variable was introduced. | 4208 // context where the variable was introduced. |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4455 context()->PlugTOS(); | 4455 context()->PlugTOS(); |
4456 } | 4456 } |
4457 } else { | 4457 } else { |
4458 context()->Plug(eax); | 4458 context()->Plug(eax); |
4459 } | 4459 } |
4460 break; | 4460 break; |
4461 } | 4461 } |
4462 case KEYED_PROPERTY: { | 4462 case KEYED_PROPERTY: { |
4463 __ pop(ecx); | 4463 __ pop(ecx); |
4464 __ pop(edx); | 4464 __ pop(edx); |
4465 Handle<Code> ic = is_classic_mode() | 4465 Handle<Code> ic = is_sloppy_mode() |
4466 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4466 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4467 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4467 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4468 CallIC(ic, expr->CountStoreFeedbackId()); | 4468 CallIC(ic, expr->CountStoreFeedbackId()); |
4469 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4469 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4470 if (expr->is_postfix()) { | 4470 if (expr->is_postfix()) { |
4471 // Result is on the stack | 4471 // Result is on the stack |
4472 if (!context()->IsEffect()) { | 4472 if (!context()->IsEffect()) { |
4473 context()->PlugTOS(); | 4473 context()->PlugTOS(); |
4474 } | 4474 } |
4475 } else { | 4475 } else { |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4912 | 4912 |
4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4914 Assembler::target_address_at(call_target_address)); | 4914 Assembler::target_address_at(call_target_address)); |
4915 return OSR_AFTER_STACK_CHECK; | 4915 return OSR_AFTER_STACK_CHECK; |
4916 } | 4916 } |
4917 | 4917 |
4918 | 4918 |
4919 } } // namespace v8::internal | 4919 } } // namespace v8::internal |
4920 | 4920 |
4921 #endif // V8_TARGET_ARCH_IA32 | 4921 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |