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 2390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
| 2411 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2412 Variable* var, MemOperand location) { |
| 2413 __ mov(location, eax); |
| 2414 if (var->IsContextSlot()) { |
| 2415 __ mov(edx, eax); |
| 2416 int offset = Context::SlotOffset(var->index()); |
| 2417 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
| 2418 } |
| 2419 } |
| 2420 |
| 2421 |
| 2422 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2423 Handle<String> name, LanguageMode mode) { |
| 2424 __ push(eax); // Value. |
| 2425 __ push(esi); // Context. |
| 2426 __ push(Immediate(name)); |
| 2427 __ push(Immediate(Smi::FromInt(mode))); |
| 2428 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2429 } |
| 2430 |
| 2431 |
2411 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2432 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
2412 Token::Value op) { | 2433 Token::Value op) { |
2413 if (var->IsUnallocated()) { | 2434 if (var->IsUnallocated()) { |
2414 // Global var, const, or let. | 2435 // Global var, const, or let. |
2415 __ mov(ecx, var->name()); | 2436 __ mov(ecx, var->name()); |
2416 __ mov(edx, GlobalObjectOperand()); | 2437 __ mov(edx, GlobalObjectOperand()); |
2417 CallStoreIC(); | 2438 CallStoreIC(); |
| 2439 |
2418 } else if (op == Token::INIT_CONST) { | 2440 } else if (op == Token::INIT_CONST) { |
2419 // Const initializers need a write barrier. | 2441 // Const initializers need a write barrier. |
2420 ASSERT(!var->IsParameter()); // No const parameters. | 2442 ASSERT(!var->IsParameter()); // No const parameters. |
2421 if (var->IsStackLocal()) { | 2443 if (var->IsLookupSlot()) { |
2422 Label skip; | |
2423 __ mov(edx, StackOperand(var)); | |
2424 __ cmp(edx, isolate()->factory()->the_hole_value()); | |
2425 __ j(not_equal, &skip); | |
2426 __ mov(StackOperand(var), eax); | |
2427 __ bind(&skip); | |
2428 } else { | |
2429 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); | |
2430 // Like var declarations, const declarations are hoisted to function | |
2431 // scope. However, unlike var initializers, const initializers are | |
2432 // able to drill a hole to that function context, even from inside a | |
2433 // 'with' context. We thus bypass the normal static scope lookup for | |
2434 // var->IsContextSlot(). | |
2435 __ push(eax); | 2444 __ push(eax); |
2436 __ push(esi); | 2445 __ push(esi); |
2437 __ push(Immediate(var->name())); | 2446 __ push(Immediate(var->name())); |
2438 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2447 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2448 } else { |
| 2449 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2450 Label skip; |
| 2451 MemOperand location = VarOperand(var, ecx); |
| 2452 __ mov(edx, location); |
| 2453 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2454 __ j(not_equal, &skip, Label::kNear); |
| 2455 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2456 __ bind(&skip); |
2439 } | 2457 } |
2440 | 2458 |
2441 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2459 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2442 // Non-initializing assignment to let variable needs a write barrier. | 2460 // Non-initializing assignment to let variable needs a write barrier. |
2443 if (var->IsLookupSlot()) { | 2461 if (var->IsLookupSlot()) { |
2444 __ push(eax); // Value. | 2462 EmitCallStoreContextSlot(var->name(), language_mode()); |
2445 __ push(esi); // Context. | |
2446 __ push(Immediate(var->name())); | |
2447 __ push(Immediate(Smi::FromInt(language_mode()))); | |
2448 __ CallRuntime(Runtime::kStoreContextSlot, 4); | |
2449 } else { | 2463 } else { |
2450 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2464 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
2451 Label assign; | 2465 Label assign; |
2452 MemOperand location = VarOperand(var, ecx); | 2466 MemOperand location = VarOperand(var, ecx); |
2453 __ mov(edx, location); | 2467 __ mov(edx, location); |
2454 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2468 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2455 __ j(not_equal, &assign, Label::kNear); | 2469 __ j(not_equal, &assign, Label::kNear); |
2456 __ push(Immediate(var->name())); | 2470 __ push(Immediate(var->name())); |
2457 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2471 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2458 __ bind(&assign); | 2472 __ bind(&assign); |
2459 __ mov(location, eax); | 2473 EmitStoreToStackLocalOrContextSlot(var, location); |
2460 if (var->IsContextSlot()) { | |
2461 __ mov(edx, eax); | |
2462 int offset = Context::SlotOffset(var->index()); | |
2463 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | |
2464 } | |
2465 } | 2474 } |
2466 | 2475 |
2467 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 2476 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { |
2468 // Assignment to var or initializing assignment to let/const | 2477 // Assignment to var or initializing assignment to let/const |
2469 // in harmony mode. | 2478 // in harmony mode. |
2470 if (var->IsStackAllocated() || var->IsContextSlot()) { | 2479 if (var->IsLookupSlot()) { |
| 2480 EmitCallStoreContextSlot(var->name(), language_mode()); |
| 2481 } else { |
| 2482 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
2471 MemOperand location = VarOperand(var, ecx); | 2483 MemOperand location = VarOperand(var, ecx); |
2472 if (generate_debug_code_ && op == Token::INIT_LET) { | 2484 if (generate_debug_code_ && op == Token::INIT_LET) { |
2473 // Check for an uninitialized let binding. | 2485 // Check for an uninitialized let binding. |
2474 __ mov(edx, location); | 2486 __ mov(edx, location); |
2475 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2487 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2476 __ Check(equal, kLetBindingReInitialization); | 2488 __ Check(equal, kLetBindingReInitialization); |
2477 } | 2489 } |
2478 // Perform the assignment. | 2490 EmitStoreToStackLocalOrContextSlot(var, location); |
2479 __ mov(location, eax); | |
2480 if (var->IsContextSlot()) { | |
2481 __ mov(edx, eax); | |
2482 int offset = Context::SlotOffset(var->index()); | |
2483 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | |
2484 } | |
2485 } else { | |
2486 ASSERT(var->IsLookupSlot()); | |
2487 __ push(eax); // Value. | |
2488 __ push(esi); // Context. | |
2489 __ push(Immediate(var->name())); | |
2490 __ push(Immediate(Smi::FromInt(language_mode()))); | |
2491 __ CallRuntime(Runtime::kStoreContextSlot, 4); | |
2492 } | 2491 } |
2493 } | 2492 } |
2494 // Non-initializing assignments to consts are ignored. | 2493 // Non-initializing assignments to consts are ignored. |
2495 } | 2494 } |
2496 | 2495 |
2497 | 2496 |
2498 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2497 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2499 // Assignment to a property, using a named store IC. | 2498 // Assignment to a property, using a named store IC. |
2500 // eax : value | 2499 // eax : value |
2501 // esp[0] : receiver | 2500 // esp[0] : receiver |
(...skipping 2411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4913 | 4912 |
4914 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4915 Assembler::target_address_at(call_target_address)); | 4914 Assembler::target_address_at(call_target_address)); |
4916 return OSR_AFTER_STACK_CHECK; | 4915 return OSR_AFTER_STACK_CHECK; |
4917 } | 4916 } |
4918 | 4917 |
4919 | 4918 |
4920 } } // namespace v8::internal | 4919 } } // namespace v8::internal |
4921 | 4920 |
4922 #endif // V8_TARGET_ARCH_IA32 | 4921 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |