| 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 __ jmp(done); | 1298 __ jmp(done); |
| 1299 } | 1299 } |
| 1300 } | 1300 } |
| 1301 | 1301 |
| 1302 | 1302 |
| 1303 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1303 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1304 TypeofMode typeof_mode) { | 1304 TypeofMode typeof_mode) { |
| 1305 Variable* var = proxy->var(); | 1305 Variable* var = proxy->var(); |
| 1306 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1306 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1307 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); | 1307 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1308 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1308 __ mov(LoadDescriptor::ReceiverRegister(), NativeContextOperand()); |
| 1309 __ mov(LoadDescriptor::ReceiverRegister(), |
| 1310 ContextOperand(LoadDescriptor::ReceiverRegister(), |
| 1311 Context::EXTENSION_INDEX)); |
| 1309 __ mov(LoadDescriptor::NameRegister(), var->name()); | 1312 __ mov(LoadDescriptor::NameRegister(), var->name()); |
| 1310 __ mov(LoadDescriptor::SlotRegister(), | 1313 __ mov(LoadDescriptor::SlotRegister(), |
| 1311 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | 1314 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
| 1312 CallLoadIC(typeof_mode); | 1315 CallLoadIC(typeof_mode); |
| 1313 } | 1316 } |
| 1314 | 1317 |
| 1315 | 1318 |
| 1316 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1319 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1317 TypeofMode typeof_mode) { | 1320 TypeofMode typeof_mode) { |
| 1318 SetExpressionPosition(proxy); | 1321 SetExpressionPosition(proxy); |
| (...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2089 Label allocate, done_allocate; | 2092 Label allocate, done_allocate; |
| 2090 | 2093 |
| 2091 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); | 2094 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); |
| 2092 __ jmp(&done_allocate, Label::kNear); | 2095 __ jmp(&done_allocate, Label::kNear); |
| 2093 | 2096 |
| 2094 __ bind(&allocate); | 2097 __ bind(&allocate); |
| 2095 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2098 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
| 2096 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2099 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2097 | 2100 |
| 2098 __ bind(&done_allocate); | 2101 __ bind(&done_allocate); |
| 2099 __ mov(ebx, GlobalObjectOperand()); | 2102 __ mov(ebx, NativeContextOperand()); |
| 2100 __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset)); | |
| 2101 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 2103 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
| 2102 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2104 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
| 2103 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2105 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 2104 isolate()->factory()->empty_fixed_array()); | 2106 isolate()->factory()->empty_fixed_array()); |
| 2105 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2107 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 2106 isolate()->factory()->empty_fixed_array()); | 2108 isolate()->factory()->empty_fixed_array()); |
| 2107 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 2109 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
| 2108 __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset), | 2110 __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset), |
| 2109 isolate()->factory()->ToBoolean(done)); | 2111 isolate()->factory()->ToBoolean(done)); |
| 2110 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 2112 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2412 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 2414 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
| 2413 } | 2415 } |
| 2414 } | 2416 } |
| 2415 | 2417 |
| 2416 | 2418 |
| 2417 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2419 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
| 2418 FeedbackVectorSlot slot) { | 2420 FeedbackVectorSlot slot) { |
| 2419 if (var->IsUnallocated()) { | 2421 if (var->IsUnallocated()) { |
| 2420 // Global var, const, or let. | 2422 // Global var, const, or let. |
| 2421 __ mov(StoreDescriptor::NameRegister(), var->name()); | 2423 __ mov(StoreDescriptor::NameRegister(), var->name()); |
| 2422 __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 2424 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); |
| 2425 __ mov(StoreDescriptor::ReceiverRegister(), |
| 2426 ContextOperand(StoreDescriptor::ReceiverRegister(), |
| 2427 Context::EXTENSION_INDEX)); |
| 2423 EmitLoadStoreICSlot(slot); | 2428 EmitLoadStoreICSlot(slot); |
| 2424 CallStoreIC(); | 2429 CallStoreIC(); |
| 2425 | 2430 |
| 2426 } else if (var->mode() == LET && op != Token::INIT) { | 2431 } else if (var->mode() == LET && op != Token::INIT) { |
| 2427 // Non-initializing assignment to let variable needs a write barrier. | 2432 // Non-initializing assignment to let variable needs a write barrier. |
| 2428 DCHECK(!var->IsLookupSlot()); | 2433 DCHECK(!var->IsLookupSlot()); |
| 2429 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2434 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2430 Label assign; | 2435 Label assign; |
| 2431 MemOperand location = VarOperand(var, ecx); | 2436 MemOperand location = VarOperand(var, ecx); |
| 2432 __ mov(edx, location); | 2437 __ mov(edx, location); |
| (...skipping 1598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4031 | 4036 |
| 4032 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { | 4037 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
| 4033 ZoneList<Expression*>* args = expr->arguments(); | 4038 ZoneList<Expression*>* args = expr->arguments(); |
| 4034 DCHECK_EQ(2, args->length()); | 4039 DCHECK_EQ(2, args->length()); |
| 4035 VisitForStackValue(args->at(0)); | 4040 VisitForStackValue(args->at(0)); |
| 4036 VisitForStackValue(args->at(1)); | 4041 VisitForStackValue(args->at(1)); |
| 4037 | 4042 |
| 4038 Label runtime, done; | 4043 Label runtime, done; |
| 4039 | 4044 |
| 4040 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT); | 4045 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT); |
| 4041 __ mov(ebx, GlobalObjectOperand()); | 4046 __ mov(ebx, NativeContextOperand()); |
| 4042 __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset)); | |
| 4043 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 4047 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
| 4044 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 4048 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
| 4045 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 4049 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 4046 isolate()->factory()->empty_fixed_array()); | 4050 isolate()->factory()->empty_fixed_array()); |
| 4047 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 4051 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 4048 isolate()->factory()->empty_fixed_array()); | 4052 isolate()->factory()->empty_fixed_array()); |
| 4049 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); | 4053 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); |
| 4050 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 4054 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
| 4051 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4055 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
| 4052 __ jmp(&done, Label::kNear); | 4056 __ jmp(&done, Label::kNear); |
| 4053 | 4057 |
| 4054 __ bind(&runtime); | 4058 __ bind(&runtime); |
| 4055 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4059 __ CallRuntime(Runtime::kCreateIterResultObject, 2); |
| 4056 | 4060 |
| 4057 __ bind(&done); | 4061 __ bind(&done); |
| 4058 context()->Plug(eax); | 4062 context()->Plug(eax); |
| 4059 } | 4063 } |
| 4060 | 4064 |
| 4061 | 4065 |
| 4062 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4066 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
| 4063 // Push undefined as receiver. | 4067 // Push undefined as receiver. |
| 4064 __ push(Immediate(isolate()->factory()->undefined_value())); | 4068 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 4065 | 4069 |
| 4066 __ mov(eax, GlobalObjectOperand()); | 4070 __ LoadGlobalFunction(expr->context_index(), eax); |
| 4067 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | |
| 4068 __ mov(eax, ContextOperand(eax, expr->context_index())); | |
| 4069 } | 4071 } |
| 4070 | 4072 |
| 4071 | 4073 |
| 4072 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 4074 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 4073 ZoneList<Expression*>* args = expr->arguments(); | 4075 ZoneList<Expression*>* args = expr->arguments(); |
| 4074 int arg_count = args->length(); | 4076 int arg_count = args->length(); |
| 4075 | 4077 |
| 4076 SetCallPosition(expr, arg_count); | 4078 SetCallPosition(expr, arg_count); |
| 4077 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 4079 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 4078 __ Set(eax, arg_count); | 4080 __ Set(eax, arg_count); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4147 : Runtime::kDeleteProperty_Sloppy, | 4149 : Runtime::kDeleteProperty_Sloppy, |
| 4148 2); | 4150 2); |
| 4149 context()->Plug(eax); | 4151 context()->Plug(eax); |
| 4150 } else if (proxy != NULL) { | 4152 } else if (proxy != NULL) { |
| 4151 Variable* var = proxy->var(); | 4153 Variable* var = proxy->var(); |
| 4152 // Delete of an unqualified identifier is disallowed in strict mode but | 4154 // Delete of an unqualified identifier is disallowed in strict mode but |
| 4153 // "delete this" is allowed. | 4155 // "delete this" is allowed. |
| 4154 bool is_this = var->HasThisName(isolate()); | 4156 bool is_this = var->HasThisName(isolate()); |
| 4155 DCHECK(is_sloppy(language_mode()) || is_this); | 4157 DCHECK(is_sloppy(language_mode()) || is_this); |
| 4156 if (var->IsUnallocatedOrGlobalSlot()) { | 4158 if (var->IsUnallocatedOrGlobalSlot()) { |
| 4157 __ push(GlobalObjectOperand()); | 4159 __ mov(eax, NativeContextOperand()); |
| 4160 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
| 4158 __ push(Immediate(var->name())); | 4161 __ push(Immediate(var->name())); |
| 4159 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4162 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); |
| 4160 context()->Plug(eax); | 4163 context()->Plug(eax); |
| 4161 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4164 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4162 // Result of deleting non-global variables is false. 'this' is | 4165 // Result of deleting non-global variables is false. 'this' is |
| 4163 // not really a variable, though we implement it as one. The | 4166 // not really a variable, though we implement it as one. The |
| 4164 // subexpression does not have side effects. | 4167 // subexpression does not have side effects. |
| 4165 context()->Plug(is_this); | 4168 context()->Plug(is_this); |
| 4166 } else { | 4169 } else { |
| 4167 // Non-global variable. Call the runtime to try to delete from the | 4170 // Non-global variable. Call the runtime to try to delete from the |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4712 } | 4715 } |
| 4713 | 4716 |
| 4714 | 4717 |
| 4715 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4718 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
| 4716 Scope* closure_scope = scope()->ClosureScope(); | 4719 Scope* closure_scope = scope()->ClosureScope(); |
| 4717 if (closure_scope->is_script_scope() || | 4720 if (closure_scope->is_script_scope() || |
| 4718 closure_scope->is_module_scope()) { | 4721 closure_scope->is_module_scope()) { |
| 4719 // Contexts nested in the native context have a canonical empty function | 4722 // Contexts nested in the native context have a canonical empty function |
| 4720 // as their closure, not the anonymous closure containing the global | 4723 // as their closure, not the anonymous closure containing the global |
| 4721 // code. | 4724 // code. |
| 4722 __ mov(eax, GlobalObjectOperand()); | 4725 __ mov(eax, NativeContextOperand()); |
| 4723 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | |
| 4724 __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); | 4726 __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); |
| 4725 } else if (closure_scope->is_eval_scope()) { | 4727 } else if (closure_scope->is_eval_scope()) { |
| 4726 // Contexts nested inside eval code have the same closure as the context | 4728 // Contexts nested inside eval code have the same closure as the context |
| 4727 // calling eval, not the anonymous closure containing the eval code. | 4729 // calling eval, not the anonymous closure containing the eval code. |
| 4728 // Fetch it from the context. | 4730 // Fetch it from the context. |
| 4729 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); | 4731 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); |
| 4730 } else { | 4732 } else { |
| 4731 DCHECK(closure_scope->is_function_scope()); | 4733 DCHECK(closure_scope->is_function_scope()); |
| 4732 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4734 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4733 } | 4735 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4872 Assembler::target_address_at(call_target_address, | 4874 Assembler::target_address_at(call_target_address, |
| 4873 unoptimized_code)); | 4875 unoptimized_code)); |
| 4874 return OSR_AFTER_STACK_CHECK; | 4876 return OSR_AFTER_STACK_CHECK; |
| 4875 } | 4877 } |
| 4876 | 4878 |
| 4877 | 4879 |
| 4878 } // namespace internal | 4880 } // namespace internal |
| 4879 } // namespace v8 | 4881 } // namespace v8 |
| 4880 | 4882 |
| 4881 #endif // V8_TARGET_ARCH_IA32 | 4883 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |