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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 __ jmp(done); | 1290 __ jmp(done); |
1291 } | 1291 } |
1292 } | 1292 } |
1293 | 1293 |
1294 | 1294 |
1295 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1295 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1296 TypeofMode typeof_mode) { | 1296 TypeofMode typeof_mode) { |
1297 Variable* var = proxy->var(); | 1297 Variable* var = proxy->var(); |
1298 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1298 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
1299 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); | 1299 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
1300 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1300 __ mov(LoadDescriptor::ReceiverRegister(), NativeContextOperand()); |
| 1301 __ mov(LoadDescriptor::ReceiverRegister(), |
| 1302 ContextOperand(LoadDescriptor::ReceiverRegister(), |
| 1303 Context::EXTENSION_INDEX)); |
1301 __ mov(LoadDescriptor::NameRegister(), var->name()); | 1304 __ mov(LoadDescriptor::NameRegister(), var->name()); |
1302 __ mov(LoadDescriptor::SlotRegister(), | 1305 __ mov(LoadDescriptor::SlotRegister(), |
1303 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | 1306 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
1304 CallLoadIC(typeof_mode); | 1307 CallLoadIC(typeof_mode); |
1305 } | 1308 } |
1306 | 1309 |
1307 | 1310 |
1308 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, | 1311 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
1309 TypeofMode typeof_mode) { | 1312 TypeofMode typeof_mode) { |
1310 SetExpressionPosition(proxy); | 1313 SetExpressionPosition(proxy); |
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 Label allocate, done_allocate; | 2084 Label allocate, done_allocate; |
2082 | 2085 |
2083 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); | 2086 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); |
2084 __ jmp(&done_allocate, Label::kNear); | 2087 __ jmp(&done_allocate, Label::kNear); |
2085 | 2088 |
2086 __ bind(&allocate); | 2089 __ bind(&allocate); |
2087 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2090 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
2088 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2091 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2089 | 2092 |
2090 __ bind(&done_allocate); | 2093 __ bind(&done_allocate); |
2091 __ mov(ebx, GlobalObjectOperand()); | 2094 __ mov(ebx, NativeContextOperand()); |
2092 __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset)); | |
2093 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 2095 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
2094 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2096 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
2095 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2097 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
2096 isolate()->factory()->empty_fixed_array()); | 2098 isolate()->factory()->empty_fixed_array()); |
2097 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2099 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
2098 isolate()->factory()->empty_fixed_array()); | 2100 isolate()->factory()->empty_fixed_array()); |
2099 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 2101 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
2100 __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset), | 2102 __ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset), |
2101 isolate()->factory()->ToBoolean(done)); | 2103 isolate()->factory()->ToBoolean(done)); |
2102 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 2104 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); | 2406 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs); |
2405 } | 2407 } |
2406 } | 2408 } |
2407 | 2409 |
2408 | 2410 |
2409 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2411 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
2410 FeedbackVectorSlot slot) { | 2412 FeedbackVectorSlot slot) { |
2411 if (var->IsUnallocated()) { | 2413 if (var->IsUnallocated()) { |
2412 // Global var, const, or let. | 2414 // Global var, const, or let. |
2413 __ mov(StoreDescriptor::NameRegister(), var->name()); | 2415 __ mov(StoreDescriptor::NameRegister(), var->name()); |
2414 __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 2416 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); |
| 2417 __ mov(StoreDescriptor::ReceiverRegister(), |
| 2418 ContextOperand(StoreDescriptor::ReceiverRegister(), |
| 2419 Context::EXTENSION_INDEX)); |
2415 EmitLoadStoreICSlot(slot); | 2420 EmitLoadStoreICSlot(slot); |
2416 CallStoreIC(); | 2421 CallStoreIC(); |
2417 | 2422 |
2418 } else if (var->mode() == LET && op != Token::INIT) { | 2423 } else if (var->mode() == LET && op != Token::INIT) { |
2419 // Non-initializing assignment to let variable needs a write barrier. | 2424 // Non-initializing assignment to let variable needs a write barrier. |
2420 DCHECK(!var->IsLookupSlot()); | 2425 DCHECK(!var->IsLookupSlot()); |
2421 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2426 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2422 Label assign; | 2427 Label assign; |
2423 MemOperand location = VarOperand(var, ecx); | 2428 MemOperand location = VarOperand(var, ecx); |
2424 __ mov(edx, location); | 2429 __ mov(edx, location); |
(...skipping 1598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4023 | 4028 |
4024 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { | 4029 void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
4025 ZoneList<Expression*>* args = expr->arguments(); | 4030 ZoneList<Expression*>* args = expr->arguments(); |
4026 DCHECK_EQ(2, args->length()); | 4031 DCHECK_EQ(2, args->length()); |
4027 VisitForStackValue(args->at(0)); | 4032 VisitForStackValue(args->at(0)); |
4028 VisitForStackValue(args->at(1)); | 4033 VisitForStackValue(args->at(1)); |
4029 | 4034 |
4030 Label runtime, done; | 4035 Label runtime, done; |
4031 | 4036 |
4032 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT); | 4037 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT); |
4033 __ mov(ebx, GlobalObjectOperand()); | 4038 __ mov(ebx, NativeContextOperand()); |
4034 __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset)); | |
4035 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 4039 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
4036 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 4040 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
4037 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 4041 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
4038 isolate()->factory()->empty_fixed_array()); | 4042 isolate()->factory()->empty_fixed_array()); |
4039 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 4043 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
4040 isolate()->factory()->empty_fixed_array()); | 4044 isolate()->factory()->empty_fixed_array()); |
4041 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); | 4045 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); |
4042 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 4046 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
4043 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 4047 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
4044 __ jmp(&done, Label::kNear); | 4048 __ jmp(&done, Label::kNear); |
4045 | 4049 |
4046 __ bind(&runtime); | 4050 __ bind(&runtime); |
4047 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 4051 __ CallRuntime(Runtime::kCreateIterResultObject, 2); |
4048 | 4052 |
4049 __ bind(&done); | 4053 __ bind(&done); |
4050 context()->Plug(eax); | 4054 context()->Plug(eax); |
4051 } | 4055 } |
4052 | 4056 |
4053 | 4057 |
4054 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 4058 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
4055 // Push undefined as receiver. | 4059 // Push undefined as receiver. |
4056 __ push(Immediate(isolate()->factory()->undefined_value())); | 4060 __ push(Immediate(isolate()->factory()->undefined_value())); |
4057 | 4061 |
4058 __ mov(eax, GlobalObjectOperand()); | 4062 __ LoadGlobalFunction(expr->context_index(), eax); |
4059 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | |
4060 __ mov(eax, ContextOperand(eax, expr->context_index())); | |
4061 } | 4063 } |
4062 | 4064 |
4063 | 4065 |
4064 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 4066 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
4065 ZoneList<Expression*>* args = expr->arguments(); | 4067 ZoneList<Expression*>* args = expr->arguments(); |
4066 int arg_count = args->length(); | 4068 int arg_count = args->length(); |
4067 | 4069 |
4068 SetCallPosition(expr, arg_count); | 4070 SetCallPosition(expr, arg_count); |
4069 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 4071 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
4070 __ Set(eax, arg_count); | 4072 __ Set(eax, arg_count); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4139 : Runtime::kDeleteProperty_Sloppy, | 4141 : Runtime::kDeleteProperty_Sloppy, |
4140 2); | 4142 2); |
4141 context()->Plug(eax); | 4143 context()->Plug(eax); |
4142 } else if (proxy != NULL) { | 4144 } else if (proxy != NULL) { |
4143 Variable* var = proxy->var(); | 4145 Variable* var = proxy->var(); |
4144 // Delete of an unqualified identifier is disallowed in strict mode but | 4146 // Delete of an unqualified identifier is disallowed in strict mode but |
4145 // "delete this" is allowed. | 4147 // "delete this" is allowed. |
4146 bool is_this = var->HasThisName(isolate()); | 4148 bool is_this = var->HasThisName(isolate()); |
4147 DCHECK(is_sloppy(language_mode()) || is_this); | 4149 DCHECK(is_sloppy(language_mode()) || is_this); |
4148 if (var->IsUnallocatedOrGlobalSlot()) { | 4150 if (var->IsUnallocatedOrGlobalSlot()) { |
4149 __ push(GlobalObjectOperand()); | 4151 __ mov(eax, NativeContextOperand()); |
| 4152 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
4150 __ push(Immediate(var->name())); | 4153 __ push(Immediate(var->name())); |
4151 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4154 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); |
4152 context()->Plug(eax); | 4155 context()->Plug(eax); |
4153 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4156 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4154 // Result of deleting non-global variables is false. 'this' is | 4157 // Result of deleting non-global variables is false. 'this' is |
4155 // not really a variable, though we implement it as one. The | 4158 // not really a variable, though we implement it as one. The |
4156 // subexpression does not have side effects. | 4159 // subexpression does not have side effects. |
4157 context()->Plug(is_this); | 4160 context()->Plug(is_this); |
4158 } else { | 4161 } else { |
4159 // Non-global variable. Call the runtime to try to delete from the | 4162 // 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... |
4704 } | 4707 } |
4705 | 4708 |
4706 | 4709 |
4707 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { | 4710 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
4708 Scope* closure_scope = scope()->ClosureScope(); | 4711 Scope* closure_scope = scope()->ClosureScope(); |
4709 if (closure_scope->is_script_scope() || | 4712 if (closure_scope->is_script_scope() || |
4710 closure_scope->is_module_scope()) { | 4713 closure_scope->is_module_scope()) { |
4711 // Contexts nested in the native context have a canonical empty function | 4714 // Contexts nested in the native context have a canonical empty function |
4712 // as their closure, not the anonymous closure containing the global | 4715 // as their closure, not the anonymous closure containing the global |
4713 // code. | 4716 // code. |
4714 __ mov(eax, GlobalObjectOperand()); | 4717 __ mov(eax, NativeContextOperand()); |
4715 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | |
4716 __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); | 4718 __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); |
4717 } else if (closure_scope->is_eval_scope()) { | 4719 } else if (closure_scope->is_eval_scope()) { |
4718 // Contexts nested inside eval code have the same closure as the context | 4720 // Contexts nested inside eval code have the same closure as the context |
4719 // calling eval, not the anonymous closure containing the eval code. | 4721 // calling eval, not the anonymous closure containing the eval code. |
4720 // Fetch it from the context. | 4722 // Fetch it from the context. |
4721 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); | 4723 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); |
4722 } else { | 4724 } else { |
4723 DCHECK(closure_scope->is_function_scope()); | 4725 DCHECK(closure_scope->is_function_scope()); |
4724 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4726 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4725 } | 4727 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4864 Assembler::target_address_at(call_target_address, | 4866 Assembler::target_address_at(call_target_address, |
4865 unoptimized_code)); | 4867 unoptimized_code)); |
4866 return OSR_AFTER_STACK_CHECK; | 4868 return OSR_AFTER_STACK_CHECK; |
4867 } | 4869 } |
4868 | 4870 |
4869 | 4871 |
4870 } // namespace internal | 4872 } // namespace internal |
4871 } // namespace v8 | 4873 } // namespace v8 |
4872 | 4874 |
4873 #endif // V8_TARGET_ARCH_X87 | 4875 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |