| 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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 | 140 |
| 141 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 141 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 142 | 142 |
| 143 #ifdef DEBUG | 143 #ifdef DEBUG |
| 144 if (strlen(FLAG_stop_at) > 0 && | 144 if (strlen(FLAG_stop_at) > 0 && |
| 145 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 145 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 146 __ stop("stop-at"); | 146 __ stop("stop-at"); |
| 147 } | 147 } |
| 148 #endif | 148 #endif |
| 149 | 149 |
| 150 // Classic mode functions and builtins need to replace the receiver with the | 150 // Sloppy mode functions and builtins need to replace the receiver with the |
| 151 // global proxy when called as functions (without an explicit receiver | 151 // global proxy when called as functions (without an explicit receiver |
| 152 // object). | 152 // object). |
| 153 if (info->is_classic_mode() && !info->is_native()) { | 153 if (info->is_sloppy_mode() && !info->is_native()) { |
| 154 Label ok; | 154 Label ok; |
| 155 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 155 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
| 156 __ ldr(r2, MemOperand(sp, receiver_offset)); | 156 __ ldr(r2, MemOperand(sp, receiver_offset)); |
| 157 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); | 157 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 158 __ b(ne, &ok); | 158 __ b(ne, &ok); |
| 159 | 159 |
| 160 __ ldr(r2, GlobalObjectOperand()); | 160 __ ldr(r2, GlobalObjectOperand()); |
| 161 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); | 161 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |
| 162 | 162 |
| 163 __ str(r2, MemOperand(sp, receiver_offset)); | 163 __ str(r2, MemOperand(sp, receiver_offset)); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 __ add(r2, fp, | 257 __ add(r2, fp, |
| 258 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 258 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
| 259 __ mov(r1, Operand(Smi::FromInt(num_parameters))); | 259 __ mov(r1, Operand(Smi::FromInt(num_parameters))); |
| 260 __ Push(r3, r2, r1); | 260 __ Push(r3, r2, r1); |
| 261 | 261 |
| 262 // Arguments to ArgumentsAccessStub: | 262 // Arguments to ArgumentsAccessStub: |
| 263 // function, receiver address, parameter count. | 263 // function, receiver address, parameter count. |
| 264 // The stub will rewrite receiever and parameter count if the previous | 264 // The stub will rewrite receiever and parameter count if the previous |
| 265 // stack frame was an arguments adapter frame. | 265 // stack frame was an arguments adapter frame. |
| 266 ArgumentsAccessStub::Type type; | 266 ArgumentsAccessStub::Type type; |
| 267 if (!is_classic_mode()) { | 267 if (!is_sloppy_mode()) { |
| 268 type = ArgumentsAccessStub::NEW_STRICT; | 268 type = ArgumentsAccessStub::NEW_STRICT; |
| 269 } else if (function()->has_duplicate_parameters()) { | 269 } else if (function()->has_duplicate_parameters()) { |
| 270 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 270 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
| 271 } else { | 271 } else { |
| 272 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 272 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
| 273 } | 273 } |
| 274 ArgumentsAccessStub stub(type); | 274 ArgumentsAccessStub stub(type); |
| 275 __ CallStub(&stub); | 275 __ CallStub(&stub); |
| 276 | 276 |
| 277 SetVar(arguments, r0, r1, r2); | 277 SetVar(arguments, r0, r1, r2); |
| 278 } | 278 } |
| 279 | 279 |
| 280 if (FLAG_trace) { | 280 if (FLAG_trace) { |
| 281 __ CallRuntime(Runtime::kTraceEnter, 0); | 281 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 282 } | 282 } |
| (...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1354 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, |
| 1355 TypeofState typeof_state, | 1355 TypeofState typeof_state, |
| 1356 Label* slow) { | 1356 Label* slow) { |
| 1357 Register current = cp; | 1357 Register current = cp; |
| 1358 Register next = r1; | 1358 Register next = r1; |
| 1359 Register temp = r2; | 1359 Register temp = r2; |
| 1360 | 1360 |
| 1361 Scope* s = scope(); | 1361 Scope* s = scope(); |
| 1362 while (s != NULL) { | 1362 while (s != NULL) { |
| 1363 if (s->num_heap_slots() > 0) { | 1363 if (s->num_heap_slots() > 0) { |
| 1364 if (s->calls_non_strict_eval()) { | 1364 if (s->calls_sloppy_eval()) { |
| 1365 // Check that extension is NULL. | 1365 // Check that extension is NULL. |
| 1366 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | 1366 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); |
| 1367 __ tst(temp, temp); | 1367 __ tst(temp, temp); |
| 1368 __ b(ne, slow); | 1368 __ b(ne, slow); |
| 1369 } | 1369 } |
| 1370 // Load next context in chain. | 1370 // Load next context in chain. |
| 1371 __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX)); | 1371 __ ldr(next, ContextOperand(current, Context::PREVIOUS_INDEX)); |
| 1372 // Walk the rest of the chain without clobbering cp. | 1372 // Walk the rest of the chain without clobbering cp. |
| 1373 current = next; | 1373 current = next; |
| 1374 } | 1374 } |
| 1375 // If no outer scope calls eval, we do not need to check more | 1375 // If no outer scope calls eval, we do not need to check more |
| 1376 // context extensions. | 1376 // context extensions. |
| 1377 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 1377 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; |
| 1378 s = s->outer_scope(); | 1378 s = s->outer_scope(); |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 if (s->is_eval_scope()) { | 1381 if (s->is_eval_scope()) { |
| 1382 Label loop, fast; | 1382 Label loop, fast; |
| 1383 if (!current.is(next)) { | 1383 if (!current.is(next)) { |
| 1384 __ Move(next, current); | 1384 __ Move(next, current); |
| 1385 } | 1385 } |
| 1386 __ bind(&loop); | 1386 __ bind(&loop); |
| 1387 // Terminate at native context. | 1387 // Terminate at native context. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1410 | 1410 |
| 1411 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1411 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1412 Label* slow) { | 1412 Label* slow) { |
| 1413 ASSERT(var->IsContextSlot()); | 1413 ASSERT(var->IsContextSlot()); |
| 1414 Register context = cp; | 1414 Register context = cp; |
| 1415 Register next = r3; | 1415 Register next = r3; |
| 1416 Register temp = r4; | 1416 Register temp = r4; |
| 1417 | 1417 |
| 1418 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1418 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| 1419 if (s->num_heap_slots() > 0) { | 1419 if (s->num_heap_slots() > 0) { |
| 1420 if (s->calls_non_strict_eval()) { | 1420 if (s->calls_sloppy_eval()) { |
| 1421 // Check that extension is NULL. | 1421 // Check that extension is NULL. |
| 1422 __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); | 1422 __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); |
| 1423 __ tst(temp, temp); | 1423 __ tst(temp, temp); |
| 1424 __ b(ne, slow); | 1424 __ b(ne, slow); |
| 1425 } | 1425 } |
| 1426 __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1426 __ ldr(next, ContextOperand(context, Context::PREVIOUS_INDEX)); |
| 1427 // Walk the rest of the chain without clobbering cp. | 1427 // Walk the rest of the chain without clobbering cp. |
| 1428 context = next; | 1428 context = next; |
| 1429 } | 1429 } |
| 1430 } | 1430 } |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2438 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2438 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2439 CallStoreIC(); | 2439 CallStoreIC(); |
| 2440 break; | 2440 break; |
| 2441 } | 2441 } |
| 2442 case KEYED_PROPERTY: { | 2442 case KEYED_PROPERTY: { |
| 2443 __ push(r0); // Preserve value. | 2443 __ push(r0); // Preserve value. |
| 2444 VisitForStackValue(prop->obj()); | 2444 VisitForStackValue(prop->obj()); |
| 2445 VisitForAccumulatorValue(prop->key()); | 2445 VisitForAccumulatorValue(prop->key()); |
| 2446 __ mov(r1, r0); | 2446 __ mov(r1, r0); |
| 2447 __ Pop(r0, r2); // r0 = restored value. | 2447 __ Pop(r0, r2); // r0 = restored value. |
| 2448 Handle<Code> ic = is_classic_mode() | 2448 Handle<Code> ic = is_sloppy_mode() |
| 2449 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2449 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2450 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2450 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2451 CallIC(ic); | 2451 CallIC(ic); |
| 2452 break; | 2452 break; |
| 2453 } | 2453 } |
| 2454 } | 2454 } |
| 2455 context()->Plug(r0); | 2455 context()->Plug(r0); |
| 2456 } | 2456 } |
| 2457 | 2457 |
| 2458 | 2458 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2564 } | 2564 } |
| 2565 | 2565 |
| 2566 | 2566 |
| 2567 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2567 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2568 // Assignment to a property, using a keyed store IC. | 2568 // Assignment to a property, using a keyed store IC. |
| 2569 | 2569 |
| 2570 // Record source code position before IC call. | 2570 // Record source code position before IC call. |
| 2571 SetSourcePosition(expr->position()); | 2571 SetSourcePosition(expr->position()); |
| 2572 __ Pop(r2, r1); // r1 = key. | 2572 __ Pop(r2, r1); // r1 = key. |
| 2573 | 2573 |
| 2574 Handle<Code> ic = is_classic_mode() | 2574 Handle<Code> ic = is_sloppy_mode() |
| 2575 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2575 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2576 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2576 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2577 CallIC(ic, expr->AssignmentFeedbackId()); | 2577 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2578 | 2578 |
| 2579 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2579 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2580 context()->Plug(r0); | 2580 context()->Plug(r0); |
| 2581 } | 2581 } |
| 2582 | 2582 |
| 2583 | 2583 |
| 2584 void FullCodeGenerator::VisitProperty(Property* expr) { | 2584 void FullCodeGenerator::VisitProperty(Property* expr) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 int arg_count = args->length(); | 2617 int arg_count = args->length(); |
| 2618 | 2618 |
| 2619 CallFunctionFlags flags; | 2619 CallFunctionFlags flags; |
| 2620 // Get the target function. | 2620 // Get the target function. |
| 2621 if (callee->IsVariableProxy()) { | 2621 if (callee->IsVariableProxy()) { |
| 2622 { StackValueContext context(this); | 2622 { StackValueContext context(this); |
| 2623 EmitVariableLoad(callee->AsVariableProxy()); | 2623 EmitVariableLoad(callee->AsVariableProxy()); |
| 2624 PrepareForBailout(callee, NO_REGISTERS); | 2624 PrepareForBailout(callee, NO_REGISTERS); |
| 2625 } | 2625 } |
| 2626 // Push undefined as receiver. This is patched in the method prologue if it | 2626 // Push undefined as receiver. This is patched in the method prologue if it |
| 2627 // is a classic mode method. | 2627 // is a sloppy mode method. |
| 2628 __ Push(isolate()->factory()->undefined_value()); | 2628 __ Push(isolate()->factory()->undefined_value()); |
| 2629 flags = NO_CALL_FUNCTION_FLAGS; | 2629 flags = NO_CALL_FUNCTION_FLAGS; |
| 2630 } else { | 2630 } else { |
| 2631 // Load the function from the receiver. | 2631 // Load the function from the receiver. |
| 2632 ASSERT(callee->IsProperty()); | 2632 ASSERT(callee->IsProperty()); |
| 2633 __ ldr(r0, MemOperand(sp, 0)); | 2633 __ ldr(r0, MemOperand(sp, 0)); |
| 2634 EmitNamedPropertyLoad(callee->AsProperty()); | 2634 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2635 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2635 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2636 // Push the target function under the receiver. | 2636 // Push the target function under the receiver. |
| 2637 __ ldr(ip, MemOperand(sp, 0)); | 2637 __ ldr(ip, MemOperand(sp, 0)); |
| (...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4178 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4178 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4179 switch (expr->op()) { | 4179 switch (expr->op()) { |
| 4180 case Token::DELETE: { | 4180 case Token::DELETE: { |
| 4181 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4181 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4182 Property* property = expr->expression()->AsProperty(); | 4182 Property* property = expr->expression()->AsProperty(); |
| 4183 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4183 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4184 | 4184 |
| 4185 if (property != NULL) { | 4185 if (property != NULL) { |
| 4186 VisitForStackValue(property->obj()); | 4186 VisitForStackValue(property->obj()); |
| 4187 VisitForStackValue(property->key()); | 4187 VisitForStackValue(property->key()); |
| 4188 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) | 4188 StrictModeFlag strict_mode_flag = (language_mode() == SLOPPY_MODE) |
| 4189 ? kNonStrictMode : kStrictMode; | 4189 ? kSloppyMode : kStrictMode; |
| 4190 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag))); | 4190 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag))); |
| 4191 __ push(r1); | 4191 __ push(r1); |
| 4192 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4192 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4193 context()->Plug(r0); | 4193 context()->Plug(r0); |
| 4194 } else if (proxy != NULL) { | 4194 } else if (proxy != NULL) { |
| 4195 Variable* var = proxy->var(); | 4195 Variable* var = proxy->var(); |
| 4196 // Delete of an unqualified identifier is disallowed in strict mode | 4196 // Delete of an unqualified identifier is disallowed in strict mode |
| 4197 // but "delete this" is allowed. | 4197 // but "delete this" is allowed. |
| 4198 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); | 4198 ASSERT(language_mode() == SLOPPY_MODE || var->is_this()); |
| 4199 if (var->IsUnallocated()) { | 4199 if (var->IsUnallocated()) { |
| 4200 __ ldr(r2, GlobalObjectOperand()); | 4200 __ ldr(r2, GlobalObjectOperand()); |
| 4201 __ mov(r1, Operand(var->name())); | 4201 __ mov(r1, Operand(var->name())); |
| 4202 __ mov(r0, Operand(Smi::FromInt(kNonStrictMode))); | 4202 __ mov(r0, Operand(Smi::FromInt(kSloppyMode))); |
| 4203 __ Push(r2, r1, r0); | 4203 __ Push(r2, r1, r0); |
| 4204 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4204 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4205 context()->Plug(r0); | 4205 context()->Plug(r0); |
| 4206 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4206 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4207 // Result of deleting non-global, non-dynamic variables is false. | 4207 // Result of deleting non-global, non-dynamic variables is false. |
| 4208 // The subexpression does not have side effects. | 4208 // The subexpression does not have side effects. |
| 4209 context()->Plug(var->is_this()); | 4209 context()->Plug(var->is_this()); |
| 4210 } else { | 4210 } else { |
| 4211 // Non-global variable. Call the runtime to try to delete from the | 4211 // Non-global variable. Call the runtime to try to delete from the |
| 4212 // context where the variable was introduced. | 4212 // context where the variable was introduced. |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4446 if (!context()->IsEffect()) { | 4446 if (!context()->IsEffect()) { |
| 4447 context()->PlugTOS(); | 4447 context()->PlugTOS(); |
| 4448 } | 4448 } |
| 4449 } else { | 4449 } else { |
| 4450 context()->Plug(r0); | 4450 context()->Plug(r0); |
| 4451 } | 4451 } |
| 4452 break; | 4452 break; |
| 4453 } | 4453 } |
| 4454 case KEYED_PROPERTY: { | 4454 case KEYED_PROPERTY: { |
| 4455 __ Pop(r2, r1); // r1 = key. r2 = receiver. | 4455 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4456 Handle<Code> ic = is_classic_mode() | 4456 Handle<Code> ic = is_sloppy_mode() |
| 4457 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4457 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4458 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4458 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4459 CallIC(ic, expr->CountStoreFeedbackId()); | 4459 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4460 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4460 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4461 if (expr->is_postfix()) { | 4461 if (expr->is_postfix()) { |
| 4462 if (!context()->IsEffect()) { | 4462 if (!context()->IsEffect()) { |
| 4463 context()->PlugTOS(); | 4463 context()->PlugTOS(); |
| 4464 } | 4464 } |
| 4465 } else { | 4465 } else { |
| 4466 context()->Plug(r0); | 4466 context()->Plug(r0); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4918 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4918 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4919 reinterpret_cast<uint32_t>( | 4919 reinterpret_cast<uint32_t>( |
| 4920 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4920 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4921 return OSR_AFTER_STACK_CHECK; | 4921 return OSR_AFTER_STACK_CHECK; |
| 4922 } | 4922 } |
| 4923 | 4923 |
| 4924 | 4924 |
| 4925 } } // namespace v8::internal | 4925 } } // namespace v8::internal |
| 4926 | 4926 |
| 4927 #endif // V8_TARGET_ARCH_ARM | 4927 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |