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 2459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2470 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2470 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2471 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2471 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2472 CallIC(ic); | 2472 CallIC(ic); |
2473 break; | 2473 break; |
2474 } | 2474 } |
2475 } | 2475 } |
2476 context()->Plug(v0); | 2476 context()->Plug(v0); |
2477 } | 2477 } |
2478 | 2478 |
2479 | 2479 |
| 2480 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2481 Variable* var, MemOperand location) { |
| 2482 __ sw(result_register(), location); |
| 2483 if (var->IsContextSlot()) { |
| 2484 // RecordWrite may destroy all its register arguments. |
| 2485 __ Move(a3, result_register()); |
| 2486 int offset = Context::SlotOffset(var->index()); |
| 2487 __ RecordWriteContextSlot( |
| 2488 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); |
| 2489 } |
| 2490 } |
| 2491 |
| 2492 |
| 2493 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2494 Handle<String> name, LanguageMode mode) { |
| 2495 __ li(a1, Operand(name)); |
| 2496 __ li(a0, Operand(Smi::FromInt(mode))); |
| 2497 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. |
| 2498 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2499 } |
| 2500 |
| 2501 |
2480 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2502 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
2481 Token::Value op) { | 2503 Token::Value op) { |
2482 if (var->IsUnallocated()) { | 2504 if (var->IsUnallocated()) { |
2483 // Global var, const, or let. | 2505 // Global var, const, or let. |
2484 __ mov(a0, result_register()); | 2506 __ mov(a0, result_register()); |
2485 __ li(a2, Operand(var->name())); | 2507 __ li(a2, Operand(var->name())); |
2486 __ lw(a1, GlobalObjectOperand()); | 2508 __ lw(a1, GlobalObjectOperand()); |
2487 CallStoreIC(); | 2509 CallStoreIC(); |
| 2510 |
2488 } else if (op == Token::INIT_CONST) { | 2511 } else if (op == Token::INIT_CONST) { |
2489 // Const initializers need a write barrier. | 2512 // Const initializers need a write barrier. |
2490 ASSERT(!var->IsParameter()); // No const parameters. | 2513 ASSERT(!var->IsParameter()); // No const parameters. |
2491 if (var->IsStackLocal()) { | 2514 if (var->IsLookupSlot()) { |
2492 Label skip; | |
2493 __ lw(a1, StackOperand(var)); | |
2494 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | |
2495 __ Branch(&skip, ne, a1, Operand(t0)); | |
2496 __ sw(result_register(), StackOperand(var)); | |
2497 __ bind(&skip); | |
2498 } else { | |
2499 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); | |
2500 // Like var declarations, const declarations are hoisted to function | |
2501 // scope. However, unlike var initializers, const initializers are | |
2502 // able to drill a hole to that function context, even from inside a | |
2503 // 'with' context. We thus bypass the normal static scope lookup for | |
2504 // var->IsContextSlot(). | |
2505 __ li(a0, Operand(var->name())); | 2515 __ li(a0, Operand(var->name())); |
2506 __ Push(v0, cp, a0); // Context and name. | 2516 __ Push(v0, cp, a0); // Context and name. |
2507 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2517 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2518 } else { |
| 2519 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2520 Label skip; |
| 2521 MemOperand location = VarOperand(var, a1); |
| 2522 __ lw(a2, location); |
| 2523 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2524 __ Branch(&skip, ne, a2, Operand(at)); |
| 2525 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2526 __ bind(&skip); |
2508 } | 2527 } |
2509 | 2528 |
2510 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2529 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2511 // Non-initializing assignment to let variable needs a write barrier. | 2530 // Non-initializing assignment to let variable needs a write barrier. |
2512 if (var->IsLookupSlot()) { | 2531 if (var->IsLookupSlot()) { |
2513 __ li(a1, Operand(var->name())); | 2532 EmitCallStoreContextSlot(var->name(), language_mode()); |
2514 __ li(a0, Operand(Smi::FromInt(language_mode()))); | |
2515 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. | |
2516 __ CallRuntime(Runtime::kStoreContextSlot, 4); | |
2517 } else { | 2533 } else { |
2518 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2534 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
2519 Label assign; | 2535 Label assign; |
2520 MemOperand location = VarOperand(var, a1); | 2536 MemOperand location = VarOperand(var, a1); |
2521 __ lw(a3, location); | 2537 __ lw(a3, location); |
2522 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2538 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
2523 __ Branch(&assign, ne, a3, Operand(t0)); | 2539 __ Branch(&assign, ne, a3, Operand(t0)); |
2524 __ li(a3, Operand(var->name())); | 2540 __ li(a3, Operand(var->name())); |
2525 __ push(a3); | 2541 __ push(a3); |
2526 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2542 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2527 // Perform the assignment. | 2543 // Perform the assignment. |
2528 __ bind(&assign); | 2544 __ bind(&assign); |
2529 __ sw(result_register(), location); | 2545 EmitStoreToStackLocalOrContextSlot(var, location); |
2530 if (var->IsContextSlot()) { | |
2531 // RecordWrite may destroy all its register arguments. | |
2532 __ mov(a3, result_register()); | |
2533 int offset = Context::SlotOffset(var->index()); | |
2534 __ RecordWriteContextSlot( | |
2535 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | |
2536 } | |
2537 } | 2546 } |
2538 | 2547 |
2539 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 2548 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { |
2540 // Assignment to var or initializing assignment to let/const | 2549 // Assignment to var or initializing assignment to let/const |
2541 // in harmony mode. | 2550 // in harmony mode. |
2542 if (var->IsStackAllocated() || var->IsContextSlot()) { | 2551 if (var->IsLookupSlot()) { |
| 2552 EmitCallStoreContextSlot(var->name(), language_mode()); |
| 2553 } else { |
| 2554 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); |
2543 MemOperand location = VarOperand(var, a1); | 2555 MemOperand location = VarOperand(var, a1); |
2544 if (generate_debug_code_ && op == Token::INIT_LET) { | 2556 if (generate_debug_code_ && op == Token::INIT_LET) { |
2545 // Check for an uninitialized let binding. | 2557 // Check for an uninitialized let binding. |
2546 __ lw(a2, location); | 2558 __ lw(a2, location); |
2547 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2559 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
2548 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); | 2560 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); |
2549 } | 2561 } |
2550 // Perform the assignment. | 2562 EmitStoreToStackLocalOrContextSlot(var, location); |
2551 __ sw(v0, location); | |
2552 if (var->IsContextSlot()) { | |
2553 __ mov(a3, v0); | |
2554 int offset = Context::SlotOffset(var->index()); | |
2555 __ RecordWriteContextSlot( | |
2556 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | |
2557 } | |
2558 } else { | |
2559 ASSERT(var->IsLookupSlot()); | |
2560 __ li(a1, Operand(var->name())); | |
2561 __ li(a0, Operand(Smi::FromInt(language_mode()))); | |
2562 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. | |
2563 __ CallRuntime(Runtime::kStoreContextSlot, 4); | |
2564 } | 2563 } |
2565 } | 2564 } |
2566 // Non-initializing assignments to consts are ignored. | 2565 // Non-initializing assignments to consts are ignored. |
2567 } | 2566 } |
2568 | 2567 |
2569 | 2568 |
2570 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2569 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2571 // Assignment to a property, using a named store IC. | 2570 // Assignment to a property, using a named store IC. |
2572 Property* prop = expr->target()->AsProperty(); | 2571 Property* prop = expr->target()->AsProperty(); |
2573 ASSERT(prop != NULL); | 2572 ASSERT(prop != NULL); |
2574 ASSERT(prop->key()->AsLiteral() != NULL); | 2573 ASSERT(prop->key()->AsLiteral() != NULL); |
2575 | 2574 |
2576 // Record source code position before IC call. | 2575 // Record source code position before IC call. |
(...skipping 2391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4968 Assembler::target_address_at(pc_immediate_load_address)) == | 4967 Assembler::target_address_at(pc_immediate_load_address)) == |
4969 reinterpret_cast<uint32_t>( | 4968 reinterpret_cast<uint32_t>( |
4970 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4969 isolate->builtins()->OsrAfterStackCheck()->entry())); |
4971 return OSR_AFTER_STACK_CHECK; | 4970 return OSR_AFTER_STACK_CHECK; |
4972 } | 4971 } |
4973 | 4972 |
4974 | 4973 |
4975 } } // namespace v8::internal | 4974 } } // namespace v8::internal |
4976 | 4975 |
4977 #endif // V8_TARGET_ARCH_MIPS | 4976 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |