| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 __ push(Immediate(Smi::FromInt(attr))); | 795 __ push(Immediate(Smi::FromInt(attr))); |
| 796 // Push initial value, if any. | 796 // Push initial value, if any. |
| 797 // Note: For variables we must not push an initial value (such as | 797 // Note: For variables we must not push an initial value (such as |
| 798 // 'undefined') because we may have a (legal) redeclaration and we | 798 // 'undefined') because we may have a (legal) redeclaration and we |
| 799 // must not destroy the current value. | 799 // must not destroy the current value. |
| 800 if (hole_init) { | 800 if (hole_init) { |
| 801 __ push(Immediate(isolate()->factory()->the_hole_value())); | 801 __ push(Immediate(isolate()->factory()->the_hole_value())); |
| 802 } else { | 802 } else { |
| 803 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 803 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
| 804 } | 804 } |
| 805 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 805 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
| 806 break; | 806 break; |
| 807 } | 807 } |
| 808 } | 808 } |
| 809 } | 809 } |
| 810 | 810 |
| 811 | 811 |
| 812 void FullCodeGenerator::VisitFunctionDeclaration( | 812 void FullCodeGenerator::VisitFunctionDeclaration( |
| 813 FunctionDeclaration* declaration) { | 813 FunctionDeclaration* declaration) { |
| 814 VariableProxy* proxy = declaration->proxy(); | 814 VariableProxy* proxy = declaration->proxy(); |
| 815 Variable* variable = proxy->var(); | 815 Variable* variable = proxy->var(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 848 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
| 849 break; | 849 break; |
| 850 } | 850 } |
| 851 | 851 |
| 852 case Variable::LOOKUP: { | 852 case Variable::LOOKUP: { |
| 853 Comment cmnt(masm_, "[ FunctionDeclaration"); | 853 Comment cmnt(masm_, "[ FunctionDeclaration"); |
| 854 __ push(esi); | 854 __ push(esi); |
| 855 __ push(Immediate(variable->name())); | 855 __ push(Immediate(variable->name())); |
| 856 __ push(Immediate(Smi::FromInt(NONE))); | 856 __ push(Immediate(Smi::FromInt(NONE))); |
| 857 VisitForStackValue(declaration->fun()); | 857 VisitForStackValue(declaration->fun()); |
| 858 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 858 __ CallRuntime(Runtime::kDeclareLookupSlot, 4); |
| 859 break; | 859 break; |
| 860 } | 860 } |
| 861 } | 861 } |
| 862 } | 862 } |
| 863 | 863 |
| 864 | 864 |
| 865 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 865 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 866 Variable* variable = declaration->proxy()->var(); | 866 Variable* variable = declaration->proxy()->var(); |
| 867 ASSERT(variable->location() == Variable::CONTEXT); | 867 ASSERT(variable->location() == Variable::CONTEXT); |
| 868 ASSERT(variable->interface()->IsFrozen()); | 868 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2377 Variable* var, MemOperand location) { | 2377 Variable* var, MemOperand location) { |
| 2378 __ mov(location, eax); | 2378 __ mov(location, eax); |
| 2379 if (var->IsContextSlot()) { | 2379 if (var->IsContextSlot()) { |
| 2380 __ mov(edx, eax); | 2380 __ mov(edx, eax); |
| 2381 int offset = Context::SlotOffset(var->index()); | 2381 int offset = Context::SlotOffset(var->index()); |
| 2382 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 2382 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
| 2383 } | 2383 } |
| 2384 } | 2384 } |
| 2385 | 2385 |
| 2386 | 2386 |
| 2387 void FullCodeGenerator::EmitCallStoreContextSlot( | |
| 2388 Handle<String> name, StrictMode strict_mode) { | |
| 2389 __ push(eax); // Value. | |
| 2390 __ push(esi); // Context. | |
| 2391 __ push(Immediate(name)); | |
| 2392 __ push(Immediate(Smi::FromInt(strict_mode))); | |
| 2393 __ CallRuntime(Runtime::kStoreContextSlot, 4); | |
| 2394 } | |
| 2395 | |
| 2396 | |
| 2397 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2387 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2398 Token::Value op) { | 2388 Token::Value op) { |
| 2399 if (var->IsUnallocated()) { | 2389 if (var->IsUnallocated()) { |
| 2400 // Global var, const, or let. | 2390 // Global var, const, or let. |
| 2401 __ mov(ecx, var->name()); | 2391 __ mov(ecx, var->name()); |
| 2402 __ mov(edx, GlobalObjectOperand()); | 2392 __ mov(edx, GlobalObjectOperand()); |
| 2403 CallStoreIC(); | 2393 CallStoreIC(); |
| 2404 | 2394 |
| 2405 } else if (op == Token::INIT_CONST_LEGACY) { | 2395 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2406 // Const initializers need a write barrier. | 2396 // Const initializers need a write barrier. |
| 2407 ASSERT(!var->IsParameter()); // No const parameters. | 2397 ASSERT(!var->IsParameter()); // No const parameters. |
| 2408 if (var->IsLookupSlot()) { | 2398 if (var->IsLookupSlot()) { |
| 2409 __ push(eax); | 2399 __ push(eax); |
| 2410 __ push(esi); | 2400 __ push(esi); |
| 2411 __ push(Immediate(var->name())); | 2401 __ push(Immediate(var->name())); |
| 2412 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2402 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); |
| 2413 } else { | 2403 } else { |
| 2414 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2404 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2415 Label skip; | 2405 Label skip; |
| 2416 MemOperand location = VarOperand(var, ecx); | 2406 MemOperand location = VarOperand(var, ecx); |
| 2417 __ mov(edx, location); | 2407 __ mov(edx, location); |
| 2418 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2408 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2419 __ j(not_equal, &skip, Label::kNear); | 2409 __ j(not_equal, &skip, Label::kNear); |
| 2420 EmitStoreToStackLocalOrContextSlot(var, location); | 2410 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2421 __ bind(&skip); | 2411 __ bind(&skip); |
| 2422 } | 2412 } |
| 2423 | 2413 |
| 2424 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2414 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2425 // Non-initializing assignment to let variable needs a write barrier. | 2415 // Non-initializing assignment to let variable needs a write barrier. |
| 2426 if (var->IsLookupSlot()) { | 2416 ASSERT(!var->IsLookupSlot()); |
| 2427 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2417 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2428 } else { | 2418 Label assign; |
| 2429 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2419 MemOperand location = VarOperand(var, ecx); |
| 2430 Label assign; | 2420 __ mov(edx, location); |
| 2431 MemOperand location = VarOperand(var, ecx); | 2421 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2432 __ mov(edx, location); | 2422 __ j(not_equal, &assign, Label::kNear); |
| 2433 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2423 __ push(Immediate(var->name())); |
| 2434 __ j(not_equal, &assign, Label::kNear); | 2424 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2435 __ push(Immediate(var->name())); | 2425 __ bind(&assign); |
| 2436 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2426 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2437 __ bind(&assign); | |
| 2438 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2439 } | |
| 2440 | 2427 |
| 2441 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2428 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2442 // Assignment to var or initializing assignment to let/const | |
| 2443 // in harmony mode. | |
| 2444 if (var->IsLookupSlot()) { | 2429 if (var->IsLookupSlot()) { |
| 2445 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2430 ASSERT(op == Token::ASSIGN || op == Token::INIT_VAR || |
| 2431 op == Token::ASSIGN_ADD); |
| 2432 // Assignment to var. |
| 2433 __ push(eax); // Value. |
| 2434 __ push(esi); // Context. |
| 2435 __ push(Immediate(var->name())); |
| 2436 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 2437 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
| 2446 } else { | 2438 } else { |
| 2439 // Assignment to var or initializing assignment to let/const in harmony |
| 2440 // mode. |
| 2447 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2441 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2448 MemOperand location = VarOperand(var, ecx); | 2442 MemOperand location = VarOperand(var, ecx); |
| 2449 if (generate_debug_code_ && op == Token::INIT_LET) { | 2443 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2450 // Check for an uninitialized let binding. | 2444 // Check for an uninitialized let binding. |
| 2451 __ mov(edx, location); | 2445 __ mov(edx, location); |
| 2452 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2446 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2453 __ Check(equal, kLetBindingReInitialization); | 2447 __ Check(equal, kLetBindingReInitialization); |
| 2454 } | 2448 } |
| 2455 EmitStoreToStackLocalOrContextSlot(var, location); | 2449 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2456 } | 2450 } |
| (...skipping 2345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4802 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4796 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4803 Assembler::target_address_at(call_target_address, | 4797 Assembler::target_address_at(call_target_address, |
| 4804 unoptimized_code)); | 4798 unoptimized_code)); |
| 4805 return OSR_AFTER_STACK_CHECK; | 4799 return OSR_AFTER_STACK_CHECK; |
| 4806 } | 4800 } |
| 4807 | 4801 |
| 4808 | 4802 |
| 4809 } } // namespace v8::internal | 4803 } } // namespace v8::internal |
| 4810 | 4804 |
| 4811 #endif // V8_TARGET_ARCH_IA32 | 4805 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |