| 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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 #ifdef DEBUG | 149 #ifdef DEBUG |
| 150 if (strlen(FLAG_stop_at) > 0 && | 150 if (strlen(FLAG_stop_at) > 0 && |
| 151 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 151 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 152 __ stop("stop-at"); | 152 __ stop("stop-at"); |
| 153 } | 153 } |
| 154 #endif | 154 #endif |
| 155 | 155 |
| 156 // Sloppy mode functions and builtins need to replace the receiver with the | 156 // Sloppy mode functions and builtins need to replace the receiver with the |
| 157 // global proxy when called as functions (without an explicit receiver | 157 // global proxy when called as functions (without an explicit receiver |
| 158 // object). | 158 // object). |
| 159 if (info->is_sloppy_mode() && !info->is_native()) { | 159 if (info->strict_mode() == SLOPPY && !info->is_native()) { |
| 160 Label ok; | 160 Label ok; |
| 161 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 161 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
| 162 __ lw(at, MemOperand(sp, receiver_offset)); | 162 __ lw(at, MemOperand(sp, receiver_offset)); |
| 163 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 163 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 164 __ Branch(&ok, ne, a2, Operand(at)); | 164 __ Branch(&ok, ne, a2, Operand(at)); |
| 165 | 165 |
| 166 __ lw(a2, GlobalObjectOperand()); | 166 __ lw(a2, GlobalObjectOperand()); |
| 167 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); | 167 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); |
| 168 | 168 |
| 169 __ sw(a2, MemOperand(sp, receiver_offset)); | 169 __ sw(a2, MemOperand(sp, receiver_offset)); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 __ Addu(a2, fp, | 264 __ Addu(a2, fp, |
| 265 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 265 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
| 266 __ li(a1, Operand(Smi::FromInt(num_parameters))); | 266 __ li(a1, Operand(Smi::FromInt(num_parameters))); |
| 267 __ Push(a3, a2, a1); | 267 __ Push(a3, a2, a1); |
| 268 | 268 |
| 269 // Arguments to ArgumentsAccessStub: | 269 // Arguments to ArgumentsAccessStub: |
| 270 // function, receiver address, parameter count. | 270 // function, receiver address, parameter count. |
| 271 // The stub will rewrite receiever and parameter count if the previous | 271 // The stub will rewrite receiever and parameter count if the previous |
| 272 // stack frame was an arguments adapter frame. | 272 // stack frame was an arguments adapter frame. |
| 273 ArgumentsAccessStub::Type type; | 273 ArgumentsAccessStub::Type type; |
| 274 if (!is_sloppy_mode()) { | 274 if (strict_mode() == STRICT) { |
| 275 type = ArgumentsAccessStub::NEW_STRICT; | 275 type = ArgumentsAccessStub::NEW_STRICT; |
| 276 } else if (function()->has_duplicate_parameters()) { | 276 } else if (function()->has_duplicate_parameters()) { |
| 277 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; | 277 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
| 278 } else { | 278 } else { |
| 279 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; | 279 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
| 280 } | 280 } |
| 281 ArgumentsAccessStub stub(type); | 281 ArgumentsAccessStub stub(type); |
| 282 __ CallStub(&stub); | 282 __ CallStub(&stub); |
| 283 | 283 |
| 284 SetVar(arguments, v0, a1, a2); | 284 SetVar(arguments, v0, a1, a2); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 295 scope()->VisitIllegalRedeclaration(this); | 295 scope()->VisitIllegalRedeclaration(this); |
| 296 | 296 |
| 297 } else { | 297 } else { |
| 298 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 298 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| 299 { Comment cmnt(masm_, "[ Declarations"); | 299 { Comment cmnt(masm_, "[ Declarations"); |
| 300 // For named function expressions, declare the function name as a | 300 // For named function expressions, declare the function name as a |
| 301 // constant. | 301 // constant. |
| 302 if (scope()->is_function_scope() && scope()->function() != NULL) { | 302 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 303 VariableDeclaration* function = scope()->function(); | 303 VariableDeclaration* function = scope()->function(); |
| 304 ASSERT(function->proxy()->var()->mode() == CONST || | 304 ASSERT(function->proxy()->var()->mode() == CONST || |
| 305 function->proxy()->var()->mode() == CONST_HARMONY); | 305 function->proxy()->var()->mode() == CONST_LEGACY); |
| 306 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 306 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); |
| 307 VisitVariableDeclaration(function); | 307 VisitVariableDeclaration(function); |
| 308 } | 308 } |
| 309 VisitDeclarations(scope()->declarations()); | 309 VisitDeclarations(scope()->declarations()); |
| 310 } | 310 } |
| 311 | 311 |
| 312 { Comment cmnt(masm_, "[ Stack check"); | 312 { Comment cmnt(masm_, "[ Stack check"); |
| 313 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 313 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
| 314 Label ok; | 314 Label ok; |
| 315 __ LoadRoot(t0, Heap::kStackLimitRootIndex); | 315 __ LoadRoot(t0, Heap::kStackLimitRootIndex); |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 | 796 |
| 797 | 797 |
| 798 void FullCodeGenerator::VisitVariableDeclaration( | 798 void FullCodeGenerator::VisitVariableDeclaration( |
| 799 VariableDeclaration* declaration) { | 799 VariableDeclaration* declaration) { |
| 800 // If it was not possible to allocate the variable at compile time, we | 800 // If it was not possible to allocate the variable at compile time, we |
| 801 // need to "declare" it at runtime to make sure it actually exists in the | 801 // need to "declare" it at runtime to make sure it actually exists in the |
| 802 // local context. | 802 // local context. |
| 803 VariableProxy* proxy = declaration->proxy(); | 803 VariableProxy* proxy = declaration->proxy(); |
| 804 VariableMode mode = declaration->mode(); | 804 VariableMode mode = declaration->mode(); |
| 805 Variable* variable = proxy->var(); | 805 Variable* variable = proxy->var(); |
| 806 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 806 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; |
| 807 switch (variable->location()) { | 807 switch (variable->location()) { |
| 808 case Variable::UNALLOCATED: | 808 case Variable::UNALLOCATED: |
| 809 globals_->Add(variable->name(), zone()); | 809 globals_->Add(variable->name(), zone()); |
| 810 globals_->Add(variable->binding_needs_init() | 810 globals_->Add(variable->binding_needs_init() |
| 811 ? isolate()->factory()->the_hole_value() | 811 ? isolate()->factory()->the_hole_value() |
| 812 : isolate()->factory()->undefined_value(), | 812 : isolate()->factory()->undefined_value(), |
| 813 zone()); | 813 zone()); |
| 814 break; | 814 break; |
| 815 | 815 |
| 816 case Variable::PARAMETER: | 816 case Variable::PARAMETER: |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 // space for nested functions that don't need literals cloning. If | 1329 // space for nested functions that don't need literals cloning. If |
| 1330 // we're running with the --always-opt or the --prepare-always-opt | 1330 // we're running with the --always-opt or the --prepare-always-opt |
| 1331 // flag, we need to use the runtime function so that the new function | 1331 // flag, we need to use the runtime function so that the new function |
| 1332 // we are creating here gets a chance to have its code optimized and | 1332 // we are creating here gets a chance to have its code optimized and |
| 1333 // doesn't just get a copy of the existing unoptimized code. | 1333 // doesn't just get a copy of the existing unoptimized code. |
| 1334 if (!FLAG_always_opt && | 1334 if (!FLAG_always_opt && |
| 1335 !FLAG_prepare_always_opt && | 1335 !FLAG_prepare_always_opt && |
| 1336 !pretenure && | 1336 !pretenure && |
| 1337 scope()->is_function_scope() && | 1337 scope()->is_function_scope() && |
| 1338 info->num_literals() == 0) { | 1338 info->num_literals() == 0) { |
| 1339 FastNewClosureStub stub(info->language_mode(), info->is_generator()); | 1339 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); |
| 1340 __ li(a2, Operand(info)); | 1340 __ li(a2, Operand(info)); |
| 1341 __ CallStub(&stub); | 1341 __ CallStub(&stub); |
| 1342 } else { | 1342 } else { |
| 1343 __ li(a0, Operand(info)); | 1343 __ li(a0, Operand(info)); |
| 1344 __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex | 1344 __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex |
| 1345 : Heap::kFalseValueRootIndex); | 1345 : Heap::kFalseValueRootIndex); |
| 1346 __ Push(cp, a0, a1); | 1346 __ Push(cp, a0, a1); |
| 1347 __ CallRuntime(Runtime::kNewClosure, 3); | 1347 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1348 } | 1348 } |
| 1349 context()->Plug(v0); | 1349 context()->Plug(v0); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1448 // eval-introduced variables. Eval is used a lot without | 1448 // eval-introduced variables. Eval is used a lot without |
| 1449 // introducing variables. In those cases, we do not want to | 1449 // introducing variables. In those cases, we do not want to |
| 1450 // perform a runtime call for all variables in the scope | 1450 // perform a runtime call for all variables in the scope |
| 1451 // containing the eval. | 1451 // containing the eval. |
| 1452 if (var->mode() == DYNAMIC_GLOBAL) { | 1452 if (var->mode() == DYNAMIC_GLOBAL) { |
| 1453 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 1453 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); |
| 1454 __ Branch(done); | 1454 __ Branch(done); |
| 1455 } else if (var->mode() == DYNAMIC_LOCAL) { | 1455 } else if (var->mode() == DYNAMIC_LOCAL) { |
| 1456 Variable* local = var->local_if_not_shadowed(); | 1456 Variable* local = var->local_if_not_shadowed(); |
| 1457 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); | 1457 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1458 if (local->mode() == LET || | 1458 if (local->mode() == LET || local->mode() == CONST || |
| 1459 local->mode() == CONST || | 1459 local->mode() == CONST_LEGACY) { |
| 1460 local->mode() == CONST_HARMONY) { | |
| 1461 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1460 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1462 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1461 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1463 if (local->mode() == CONST) { | 1462 if (local->mode() == CONST_LEGACY) { |
| 1464 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1463 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1465 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. | 1464 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. |
| 1466 } else { // LET || CONST_HARMONY | 1465 } else { // LET || CONST |
| 1467 __ Branch(done, ne, at, Operand(zero_reg)); | 1466 __ Branch(done, ne, at, Operand(zero_reg)); |
| 1468 __ li(a0, Operand(var->name())); | 1467 __ li(a0, Operand(var->name())); |
| 1469 __ push(a0); | 1468 __ push(a0); |
| 1470 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1469 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1471 } | 1470 } |
| 1472 } | 1471 } |
| 1473 __ Branch(done); | 1472 __ Branch(done); |
| 1474 } | 1473 } |
| 1475 } | 1474 } |
| 1476 | 1475 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 // binding is initialized: | 1522 // binding is initialized: |
| 1524 // function() { f(); let x = 1; function f() { x = 2; } } | 1523 // function() { f(); let x = 1; function f() { x = 2; } } |
| 1525 // | 1524 // |
| 1526 bool skip_init_check; | 1525 bool skip_init_check; |
| 1527 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1526 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
| 1528 skip_init_check = false; | 1527 skip_init_check = false; |
| 1529 } else { | 1528 } else { |
| 1530 // Check that we always have valid source position. | 1529 // Check that we always have valid source position. |
| 1531 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1530 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); |
| 1532 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1531 ASSERT(proxy->position() != RelocInfo::kNoPosition); |
| 1533 skip_init_check = var->mode() != CONST && | 1532 skip_init_check = var->mode() != CONST_LEGACY && |
| 1534 var->initializer_position() < proxy->position(); | 1533 var->initializer_position() < proxy->position(); |
| 1535 } | 1534 } |
| 1536 | 1535 |
| 1537 if (!skip_init_check) { | 1536 if (!skip_init_check) { |
| 1538 // Let and const need a read barrier. | 1537 // Let and const need a read barrier. |
| 1539 GetVar(v0, var); | 1538 GetVar(v0, var); |
| 1540 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1539 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1541 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1540 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1542 if (var->mode() == LET || var->mode() == CONST_HARMONY) { | 1541 if (var->mode() == LET || var->mode() == CONST) { |
| 1543 // Throw a reference error when using an uninitialized let/const | 1542 // Throw a reference error when using an uninitialized let/const |
| 1544 // binding in harmony mode. | 1543 // binding in harmony mode. |
| 1545 Label done; | 1544 Label done; |
| 1546 __ Branch(&done, ne, at, Operand(zero_reg)); | 1545 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 1547 __ li(a0, Operand(var->name())); | 1546 __ li(a0, Operand(var->name())); |
| 1548 __ push(a0); | 1547 __ push(a0); |
| 1549 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1548 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1550 __ bind(&done); | 1549 __ bind(&done); |
| 1551 } else { | 1550 } else { |
| 1552 // Uninitalized const bindings outside of harmony mode are unholed. | 1551 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1553 ASSERT(var->mode() == CONST); | 1552 ASSERT(var->mode() == CONST_LEGACY); |
| 1554 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1553 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1555 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. | 1554 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. |
| 1556 } | 1555 } |
| 1557 context()->Plug(v0); | 1556 context()->Plug(v0); |
| 1558 break; | 1557 break; |
| 1559 } | 1558 } |
| 1560 } | 1559 } |
| 1561 context()->Plug(var); | 1560 context()->Plug(var); |
| 1562 break; | 1561 break; |
| 1563 } | 1562 } |
| (...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 __ li(a2, Operand(prop->key()->AsLiteral()->value())); | 2451 __ li(a2, Operand(prop->key()->AsLiteral()->value())); |
| 2453 CallStoreIC(); | 2452 CallStoreIC(); |
| 2454 break; | 2453 break; |
| 2455 } | 2454 } |
| 2456 case KEYED_PROPERTY: { | 2455 case KEYED_PROPERTY: { |
| 2457 __ push(result_register()); // Preserve value. | 2456 __ push(result_register()); // Preserve value. |
| 2458 VisitForStackValue(prop->obj()); | 2457 VisitForStackValue(prop->obj()); |
| 2459 VisitForAccumulatorValue(prop->key()); | 2458 VisitForAccumulatorValue(prop->key()); |
| 2460 __ mov(a1, result_register()); | 2459 __ mov(a1, result_register()); |
| 2461 __ Pop(a0, a2); // a0 = restored value. | 2460 __ Pop(a0, a2); // a0 = restored value. |
| 2462 Handle<Code> ic = is_sloppy_mode() | 2461 Handle<Code> ic = strict_mode() == SLOPPY |
| 2463 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2462 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2464 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2463 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2465 CallIC(ic); | 2464 CallIC(ic); |
| 2466 break; | 2465 break; |
| 2467 } | 2466 } |
| 2468 } | 2467 } |
| 2469 context()->Plug(v0); | 2468 context()->Plug(v0); |
| 2470 } | 2469 } |
| 2471 | 2470 |
| 2472 | 2471 |
| 2473 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( | 2472 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2474 Variable* var, MemOperand location) { | 2473 Variable* var, MemOperand location) { |
| 2475 __ sw(result_register(), location); | 2474 __ sw(result_register(), location); |
| 2476 if (var->IsContextSlot()) { | 2475 if (var->IsContextSlot()) { |
| 2477 // RecordWrite may destroy all its register arguments. | 2476 // RecordWrite may destroy all its register arguments. |
| 2478 __ Move(a3, result_register()); | 2477 __ Move(a3, result_register()); |
| 2479 int offset = Context::SlotOffset(var->index()); | 2478 int offset = Context::SlotOffset(var->index()); |
| 2480 __ RecordWriteContextSlot( | 2479 __ RecordWriteContextSlot( |
| 2481 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | 2480 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); |
| 2482 } | 2481 } |
| 2483 } | 2482 } |
| 2484 | 2483 |
| 2485 | 2484 |
| 2486 void FullCodeGenerator::EmitCallStoreContextSlot( | 2485 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2487 Handle<String> name, LanguageMode mode) { | 2486 Handle<String> name, StrictMode strict_mode) { |
| 2488 __ li(a1, Operand(name)); | 2487 __ li(a1, Operand(name)); |
| 2489 __ li(a0, Operand(Smi::FromInt(mode))); | 2488 __ li(a0, Operand(Smi::FromInt(strict_mode))); |
| 2490 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. | 2489 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. |
| 2491 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 2490 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2492 } | 2491 } |
| 2493 | 2492 |
| 2494 | 2493 |
| 2495 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2494 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
| 2496 Token::Value op) { | |
| 2497 if (var->IsUnallocated()) { | 2495 if (var->IsUnallocated()) { |
| 2498 // Global var, const, or let. | 2496 // Global var, const, or let. |
| 2499 __ mov(a0, result_register()); | 2497 __ mov(a0, result_register()); |
| 2500 __ li(a2, Operand(var->name())); | 2498 __ li(a2, Operand(var->name())); |
| 2501 __ lw(a1, GlobalObjectOperand()); | 2499 __ lw(a1, GlobalObjectOperand()); |
| 2502 CallStoreIC(); | 2500 CallStoreIC(); |
| 2503 | 2501 |
| 2504 } else if (op == Token::INIT_CONST) { | 2502 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2505 // Const initializers need a write barrier. | 2503 // Const initializers need a write barrier. |
| 2506 ASSERT(!var->IsParameter()); // No const parameters. | 2504 ASSERT(!var->IsParameter()); // No const parameters. |
| 2507 if (var->IsLookupSlot()) { | 2505 if (var->IsLookupSlot()) { |
| 2508 __ li(a0, Operand(var->name())); | 2506 __ li(a0, Operand(var->name())); |
| 2509 __ Push(v0, cp, a0); // Context and name. | 2507 __ Push(v0, cp, a0); // Context and name. |
| 2510 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2508 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2511 } else { | 2509 } else { |
| 2512 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2510 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2513 Label skip; | 2511 Label skip; |
| 2514 MemOperand location = VarOperand(var, a1); | 2512 MemOperand location = VarOperand(var, a1); |
| 2515 __ lw(a2, location); | 2513 __ lw(a2, location); |
| 2516 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2514 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2517 __ Branch(&skip, ne, a2, Operand(at)); | 2515 __ Branch(&skip, ne, a2, Operand(at)); |
| 2518 EmitStoreToStackLocalOrContextSlot(var, location); | 2516 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2519 __ bind(&skip); | 2517 __ bind(&skip); |
| 2520 } | 2518 } |
| 2521 | 2519 |
| 2522 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2520 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2523 // Non-initializing assignment to let variable needs a write barrier. | 2521 // Non-initializing assignment to let variable needs a write barrier. |
| 2524 if (var->IsLookupSlot()) { | 2522 if (var->IsLookupSlot()) { |
| 2525 EmitCallStoreContextSlot(var->name(), language_mode()); | 2523 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2526 } else { | 2524 } else { |
| 2527 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2525 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2528 Label assign; | 2526 Label assign; |
| 2529 MemOperand location = VarOperand(var, a1); | 2527 MemOperand location = VarOperand(var, a1); |
| 2530 __ lw(a3, location); | 2528 __ lw(a3, location); |
| 2531 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2529 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2532 __ Branch(&assign, ne, a3, Operand(t0)); | 2530 __ Branch(&assign, ne, a3, Operand(t0)); |
| 2533 __ li(a3, Operand(var->name())); | 2531 __ li(a3, Operand(var->name())); |
| 2534 __ push(a3); | 2532 __ push(a3); |
| 2535 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2533 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2536 // Perform the assignment. | 2534 // Perform the assignment. |
| 2537 __ bind(&assign); | 2535 __ bind(&assign); |
| 2538 EmitStoreToStackLocalOrContextSlot(var, location); | 2536 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2539 } | 2537 } |
| 2540 | 2538 |
| 2541 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 2539 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2542 // Assignment to var or initializing assignment to let/const | 2540 // Assignment to var or initializing assignment to let/const |
| 2543 // in harmony mode. | 2541 // in harmony mode. |
| 2544 if (var->IsLookupSlot()) { | 2542 if (var->IsLookupSlot()) { |
| 2545 EmitCallStoreContextSlot(var->name(), language_mode()); | 2543 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2546 } else { | 2544 } else { |
| 2547 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); | 2545 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); |
| 2548 MemOperand location = VarOperand(var, a1); | 2546 MemOperand location = VarOperand(var, a1); |
| 2549 if (generate_debug_code_ && op == Token::INIT_LET) { | 2547 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2550 // Check for an uninitialized let binding. | 2548 // Check for an uninitialized let binding. |
| 2551 __ lw(a2, location); | 2549 __ lw(a2, location); |
| 2552 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2550 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2553 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); | 2551 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); |
| 2554 } | 2552 } |
| 2555 EmitStoreToStackLocalOrContextSlot(var, location); | 2553 EmitStoreToStackLocalOrContextSlot(var, location); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2584 // Record source code position before IC call. | 2582 // Record source code position before IC call. |
| 2585 SetSourcePosition(expr->position()); | 2583 SetSourcePosition(expr->position()); |
| 2586 // Call keyed store IC. | 2584 // Call keyed store IC. |
| 2587 // The arguments are: | 2585 // The arguments are: |
| 2588 // - a0 is the value, | 2586 // - a0 is the value, |
| 2589 // - a1 is the key, | 2587 // - a1 is the key, |
| 2590 // - a2 is the receiver. | 2588 // - a2 is the receiver. |
| 2591 __ mov(a0, result_register()); | 2589 __ mov(a0, result_register()); |
| 2592 __ Pop(a2, a1); // a1 = key. | 2590 __ Pop(a2, a1); // a1 = key. |
| 2593 | 2591 |
| 2594 Handle<Code> ic = is_sloppy_mode() | 2592 Handle<Code> ic = strict_mode() == SLOPPY |
| 2595 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2593 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2596 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2594 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2597 CallIC(ic, expr->AssignmentFeedbackId()); | 2595 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2598 | 2596 |
| 2599 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2597 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2600 context()->Plug(v0); | 2598 context()->Plug(v0); |
| 2601 } | 2599 } |
| 2602 | 2600 |
| 2603 | 2601 |
| 2604 void FullCodeGenerator::VisitProperty(Property* expr) { | 2602 void FullCodeGenerator::VisitProperty(Property* expr) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2750 if (arg_count > 0) { | 2748 if (arg_count > 0) { |
| 2751 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); | 2749 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); |
| 2752 } else { | 2750 } else { |
| 2753 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); | 2751 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); |
| 2754 } | 2752 } |
| 2755 | 2753 |
| 2756 // t1: the receiver of the enclosing function. | 2754 // t1: the receiver of the enclosing function. |
| 2757 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2755 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2758 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); | 2756 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); |
| 2759 | 2757 |
| 2760 // t0: the language mode. | 2758 // t0: the strict mode. |
| 2761 __ li(t0, Operand(Smi::FromInt(language_mode()))); | 2759 __ li(t0, Operand(Smi::FromInt(strict_mode()))); |
| 2762 | 2760 |
| 2763 // a1: the start position of the scope the calls resides in. | 2761 // a1: the start position of the scope the calls resides in. |
| 2764 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); | 2762 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2765 | 2763 |
| 2766 // Do the runtime call. | 2764 // Do the runtime call. |
| 2767 __ Push(t2, t1, t0, a1); | 2765 __ Push(t2, t1, t0, a1); |
| 2768 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2766 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2769 } | 2767 } |
| 2770 | 2768 |
| 2771 | 2769 |
| (...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4220 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4218 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4221 switch (expr->op()) { | 4219 switch (expr->op()) { |
| 4222 case Token::DELETE: { | 4220 case Token::DELETE: { |
| 4223 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4221 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4224 Property* property = expr->expression()->AsProperty(); | 4222 Property* property = expr->expression()->AsProperty(); |
| 4225 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4223 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4226 | 4224 |
| 4227 if (property != NULL) { | 4225 if (property != NULL) { |
| 4228 VisitForStackValue(property->obj()); | 4226 VisitForStackValue(property->obj()); |
| 4229 VisitForStackValue(property->key()); | 4227 VisitForStackValue(property->key()); |
| 4230 StrictModeFlag strict_mode_flag = (language_mode() == SLOPPY_MODE) | 4228 __ li(a1, Operand(Smi::FromInt(strict_mode()))); |
| 4231 ? kSloppyMode : kStrictMode; | |
| 4232 __ li(a1, Operand(Smi::FromInt(strict_mode_flag))); | |
| 4233 __ push(a1); | 4229 __ push(a1); |
| 4234 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4230 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4235 context()->Plug(v0); | 4231 context()->Plug(v0); |
| 4236 } else if (proxy != NULL) { | 4232 } else if (proxy != NULL) { |
| 4237 Variable* var = proxy->var(); | 4233 Variable* var = proxy->var(); |
| 4238 // Delete of an unqualified identifier is disallowed in strict mode | 4234 // Delete of an unqualified identifier is disallowed in strict mode |
| 4239 // but "delete this" is allowed. | 4235 // but "delete this" is allowed. |
| 4240 ASSERT(language_mode() == SLOPPY_MODE || var->is_this()); | 4236 ASSERT(strict_mode() == SLOPPY || var->is_this()); |
| 4241 if (var->IsUnallocated()) { | 4237 if (var->IsUnallocated()) { |
| 4242 __ lw(a2, GlobalObjectOperand()); | 4238 __ lw(a2, GlobalObjectOperand()); |
| 4243 __ li(a1, Operand(var->name())); | 4239 __ li(a1, Operand(var->name())); |
| 4244 __ li(a0, Operand(Smi::FromInt(kSloppyMode))); | 4240 __ li(a0, Operand(Smi::FromInt(SLOPPY))); |
| 4245 __ Push(a2, a1, a0); | 4241 __ Push(a2, a1, a0); |
| 4246 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4242 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4247 context()->Plug(v0); | 4243 context()->Plug(v0); |
| 4248 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4244 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4249 // Result of deleting non-global, non-dynamic variables is false. | 4245 // Result of deleting non-global, non-dynamic variables is false. |
| 4250 // The subexpression does not have side effects. | 4246 // The subexpression does not have side effects. |
| 4251 context()->Plug(var->is_this()); | 4247 context()->Plug(var->is_this()); |
| 4252 } else { | 4248 } else { |
| 4253 // Non-global variable. Call the runtime to try to delete from the | 4249 // Non-global variable. Call the runtime to try to delete from the |
| 4254 // context where the variable was introduced. | 4250 // context where the variable was introduced. |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4493 context()->PlugTOS(); | 4489 context()->PlugTOS(); |
| 4494 } | 4490 } |
| 4495 } else { | 4491 } else { |
| 4496 context()->Plug(v0); | 4492 context()->Plug(v0); |
| 4497 } | 4493 } |
| 4498 break; | 4494 break; |
| 4499 } | 4495 } |
| 4500 case KEYED_PROPERTY: { | 4496 case KEYED_PROPERTY: { |
| 4501 __ mov(a0, result_register()); // Value. | 4497 __ mov(a0, result_register()); // Value. |
| 4502 __ Pop(a2, a1); // a1 = key, a2 = receiver. | 4498 __ Pop(a2, a1); // a1 = key, a2 = receiver. |
| 4503 Handle<Code> ic = is_sloppy_mode() | 4499 Handle<Code> ic = strict_mode() == SLOPPY |
| 4504 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4500 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4505 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4501 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4506 CallIC(ic, expr->CountStoreFeedbackId()); | 4502 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4507 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4503 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4508 if (expr->is_postfix()) { | 4504 if (expr->is_postfix()) { |
| 4509 if (!context()->IsEffect()) { | 4505 if (!context()->IsEffect()) { |
| 4510 context()->PlugTOS(); | 4506 context()->PlugTOS(); |
| 4511 } | 4507 } |
| 4512 } else { | 4508 } else { |
| 4513 context()->Plug(v0); | 4509 context()->Plug(v0); |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4954 Assembler::target_address_at(pc_immediate_load_address)) == | 4950 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4955 reinterpret_cast<uint32_t>( | 4951 reinterpret_cast<uint32_t>( |
| 4956 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4952 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4957 return OSR_AFTER_STACK_CHECK; | 4953 return OSR_AFTER_STACK_CHECK; |
| 4958 } | 4954 } |
| 4959 | 4955 |
| 4960 | 4956 |
| 4961 } } // namespace v8::internal | 4957 } } // namespace v8::internal |
| 4962 | 4958 |
| 4963 #endif // V8_TARGET_ARCH_MIPS | 4959 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |