Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(812)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 7280012: Introduce scopes to keep track of catch blocks at compile time. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update to HEAD. Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 // o edi: the JS function object being called (ie, ourselves) 116 // o edi: the JS function object being called (ie, ourselves)
117 // o esi: our context 117 // o esi: our context
118 // o ebp: our caller's frame pointer 118 // o ebp: our caller's frame pointer
119 // o esp: stack pointer (pointing to return address) 119 // o esp: stack pointer (pointing to return address)
120 // 120 //
121 // The function builds a JS frame. Please see JavaScriptFrameConstants in 121 // The function builds a JS frame. Please see JavaScriptFrameConstants in
122 // frames-ia32.h for its layout. 122 // frames-ia32.h for its layout.
123 void FullCodeGenerator::Generate(CompilationInfo* info) { 123 void FullCodeGenerator::Generate(CompilationInfo* info) {
124 ASSERT(info_ == NULL); 124 ASSERT(info_ == NULL);
125 info_ = info; 125 info_ = info;
126 scope_ = info->scope();
126 SetFunctionPosition(function()); 127 SetFunctionPosition(function());
127 Comment cmnt(masm_, "[ function compiled by full code generator"); 128 Comment cmnt(masm_, "[ function compiled by full code generator");
128 129
129 #ifdef DEBUG 130 #ifdef DEBUG
130 if (strlen(FLAG_stop_at) > 0 && 131 if (strlen(FLAG_stop_at) > 0 &&
131 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 132 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
132 __ int3(); 133 __ int3();
133 } 134 }
134 #endif 135 #endif
135 136
136 // Strict mode functions and builtins need to replace the receiver 137 // Strict mode functions and builtins need to replace the receiver
137 // with undefined when called as functions (without an explicit 138 // with undefined when called as functions (without an explicit
138 // receiver object). ecx is zero for method calls and non-zero for 139 // receiver object). ecx is zero for method calls and non-zero for
139 // function calls. 140 // function calls.
140 if (info->is_strict_mode() || info->is_native()) { 141 if (info->is_strict_mode() || info->is_native()) {
141 Label ok; 142 Label ok;
142 __ test(ecx, Operand(ecx)); 143 __ test(ecx, Operand(ecx));
143 __ j(zero, &ok, Label::kNear); 144 __ j(zero, &ok, Label::kNear);
144 // +1 for return address. 145 // +1 for return address.
145 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 146 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
146 __ mov(Operand(esp, receiver_offset), 147 __ mov(Operand(esp, receiver_offset),
147 Immediate(isolate()->factory()->undefined_value())); 148 Immediate(isolate()->factory()->undefined_value()));
148 __ bind(&ok); 149 __ bind(&ok);
149 } 150 }
150 151
151 __ push(ebp); // Caller's frame pointer. 152 __ push(ebp); // Caller's frame pointer.
152 __ mov(ebp, esp); 153 __ mov(ebp, esp);
153 __ push(esi); // Callee's context. 154 __ push(esi); // Callee's context.
154 __ push(edi); // Callee's JS Function. 155 __ push(edi); // Callee's JS Function.
155 156
156 { Comment cmnt(masm_, "[ Allocate locals"); 157 { Comment cmnt(masm_, "[ Allocate locals");
157 int locals_count = scope()->num_stack_slots(); 158 int locals_count = info->scope()->num_stack_slots();
158 if (locals_count == 1) { 159 if (locals_count == 1) {
159 __ push(Immediate(isolate()->factory()->undefined_value())); 160 __ push(Immediate(isolate()->factory()->undefined_value()));
160 } else if (locals_count > 1) { 161 } else if (locals_count > 1) {
161 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); 162 __ mov(eax, Immediate(isolate()->factory()->undefined_value()));
162 for (int i = 0; i < locals_count; i++) { 163 for (int i = 0; i < locals_count; i++) {
163 __ push(eax); 164 __ push(eax);
164 } 165 }
165 } 166 }
166 } 167 }
167 168
168 bool function_in_register = true; 169 bool function_in_register = true;
169 170
170 // Possibly allocate a local context. 171 // Possibly allocate a local context.
171 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 172 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
172 if (heap_slots > 0) { 173 if (heap_slots > 0) {
173 Comment cmnt(masm_, "[ Allocate local context"); 174 Comment cmnt(masm_, "[ Allocate local context");
174 // Argument to NewContext is the function, which is still in edi. 175 // Argument to NewContext is the function, which is still in edi.
175 __ push(edi); 176 __ push(edi);
176 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 177 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
177 FastNewContextStub stub(heap_slots); 178 FastNewContextStub stub(heap_slots);
178 __ CallStub(&stub); 179 __ CallStub(&stub);
179 } else { 180 } else {
180 __ CallRuntime(Runtime::kNewFunctionContext, 1); 181 __ CallRuntime(Runtime::kNewFunctionContext, 1);
181 } 182 }
182 function_in_register = false; 183 function_in_register = false;
183 // Context is returned in both eax and esi. It replaces the context 184 // Context is returned in both eax and esi. It replaces the context
184 // passed to us. It's saved in the stack and kept live in esi. 185 // passed to us. It's saved in the stack and kept live in esi.
185 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 186 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
186 187
187 // Copy parameters into context if necessary. 188 // Copy parameters into context if necessary.
188 int num_parameters = scope()->num_parameters(); 189 int num_parameters = info->scope()->num_parameters();
189 for (int i = 0; i < num_parameters; i++) { 190 for (int i = 0; i < num_parameters; i++) {
190 Slot* slot = scope()->parameter(i)->AsSlot(); 191 Slot* slot = scope()->parameter(i)->AsSlot();
191 if (slot != NULL && slot->type() == Slot::CONTEXT) { 192 if (slot != NULL && slot->type() == Slot::CONTEXT) {
192 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 193 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
193 (num_parameters - 1 - i) * kPointerSize; 194 (num_parameters - 1 - i) * kPointerSize;
194 // Load parameter from stack. 195 // Load parameter from stack.
195 __ mov(eax, Operand(ebp, parameter_offset)); 196 __ mov(eax, Operand(ebp, parameter_offset));
196 // Store it in the context. 197 // Store it in the context.
197 int context_offset = Context::SlotOffset(slot->index()); 198 int context_offset = Context::SlotOffset(slot->index());
198 __ mov(Operand(esi, context_offset), eax); 199 __ mov(Operand(esi, context_offset), eax);
199 // Update the write barrier. This clobbers all involved 200 // Update the write barrier. This clobbers all involved
200 // registers, so we have use a third register to avoid 201 // registers, so we have use a third register to avoid
201 // clobbering esi. 202 // clobbering esi.
202 __ mov(ecx, esi); 203 __ mov(ecx, esi);
203 __ RecordWrite(ecx, context_offset, eax, ebx); 204 __ RecordWrite(ecx, context_offset, eax, ebx);
204 } 205 }
205 } 206 }
206 } 207 }
207 208
208 Variable* arguments = scope()->arguments(); 209 Variable* arguments = scope()->arguments();
209 if (arguments != NULL) { 210 if (arguments != NULL) {
210 // Function uses arguments object. 211 // Function uses arguments object.
211 Comment cmnt(masm_, "[ Allocate arguments object"); 212 Comment cmnt(masm_, "[ Allocate arguments object");
212 if (function_in_register) { 213 if (function_in_register) {
213 __ push(edi); 214 __ push(edi);
214 } else { 215 } else {
215 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 216 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
216 } 217 }
217 // Receiver is just before the parameters on the caller's stack. 218 // Receiver is just before the parameters on the caller's stack.
218 int offset = scope()->num_parameters() * kPointerSize; 219 int num_parameters = info->scope()->num_parameters();
220 int offset = num_parameters * kPointerSize;
219 __ lea(edx, 221 __ lea(edx,
220 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 222 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
221 __ push(edx); 223 __ push(edx);
222 __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters()))); 224 __ SafePush(Immediate(Smi::FromInt(num_parameters)));
223 // Arguments to ArgumentsAccessStub and/or New...: 225 // Arguments to ArgumentsAccessStub and/or New...:
224 // function, receiver address, parameter count. 226 // function, receiver address, parameter count.
225 // The stub will rewrite receiver and parameter count if the previous 227 // The stub will rewrite receiver and parameter count if the previous
226 // stack frame was an arguments adapter frame. 228 // stack frame was an arguments adapter frame.
227 ArgumentsAccessStub::Type type; 229 ArgumentsAccessStub::Type type;
228 if (is_strict_mode()) { 230 if (is_strict_mode()) {
229 type = ArgumentsAccessStub::NEW_STRICT; 231 type = ArgumentsAccessStub::NEW_STRICT;
230 } else if (function()->has_duplicate_parameters()) { 232 } else if (function()->has_duplicate_parameters()) {
231 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; 233 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
232 } else { 234 } else {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 Label check_exit_codesize; 339 Label check_exit_codesize;
338 masm_->bind(&check_exit_codesize); 340 masm_->bind(&check_exit_codesize);
339 #endif 341 #endif
340 SetSourcePosition(function()->end_position() - 1); 342 SetSourcePosition(function()->end_position() - 1);
341 __ RecordJSReturn(); 343 __ RecordJSReturn();
342 // Do not use the leave instruction here because it is too short to 344 // Do not use the leave instruction here because it is too short to
343 // patch with the code required by the debugger. 345 // patch with the code required by the debugger.
344 __ mov(esp, ebp); 346 __ mov(esp, ebp);
345 __ pop(ebp); 347 __ pop(ebp);
346 348
347 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize; 349 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
348 __ Ret(arguments_bytes, ecx); 350 __ Ret(arguments_bytes, ecx);
349 #ifdef ENABLE_DEBUGGER_SUPPORT 351 #ifdef ENABLE_DEBUGGER_SUPPORT
350 // Check that the size of the code used for returning is large enough 352 // Check that the size of the code used for returning is large enough
351 // for the debugger's requirements. 353 // for the debugger's requirements.
352 ASSERT(Assembler::kJSReturnSequenceLength <= 354 ASSERT(Assembler::kJSReturnSequenceLength <=
353 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 355 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
354 #endif 356 #endif
355 } 357 }
356 } 358 }
357 359
(...skipping 1696 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, 2056 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2055 int arg_count) { 2057 int arg_count) {
2056 // Push copy of the first argument or undefined if it doesn't exist. 2058 // Push copy of the first argument or undefined if it doesn't exist.
2057 if (arg_count > 0) { 2059 if (arg_count > 0) {
2058 __ push(Operand(esp, arg_count * kPointerSize)); 2060 __ push(Operand(esp, arg_count * kPointerSize));
2059 } else { 2061 } else {
2060 __ push(Immediate(isolate()->factory()->undefined_value())); 2062 __ push(Immediate(isolate()->factory()->undefined_value()));
2061 } 2063 }
2062 2064
2063 // Push the receiver of the enclosing function. 2065 // Push the receiver of the enclosing function.
2064 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 2066 __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2065 2067
2066 // Push the strict mode flag. 2068 // Push the strict mode flag.
2067 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 2069 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
2068 2070
2069 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP 2071 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2070 ? Runtime::kResolvePossiblyDirectEvalNoLookup 2072 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2071 : Runtime::kResolvePossiblyDirectEval, 4); 2073 : Runtime::kResolvePossiblyDirectEval, 4);
2072 } 2074 }
2073 2075
2074 2076
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
2597 } 2599 }
2598 2600
2599 2601
2600 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2602 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2601 ASSERT(args->length() == 1); 2603 ASSERT(args->length() == 1);
2602 2604
2603 // ArgumentsAccessStub expects the key in edx and the formal 2605 // ArgumentsAccessStub expects the key in edx and the formal
2604 // parameter count in eax. 2606 // parameter count in eax.
2605 VisitForAccumulatorValue(args->at(0)); 2607 VisitForAccumulatorValue(args->at(0));
2606 __ mov(edx, eax); 2608 __ mov(edx, eax);
2607 __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2609 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2608 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2610 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2609 __ CallStub(&stub); 2611 __ CallStub(&stub);
2610 context()->Plug(eax); 2612 context()->Plug(eax);
2611 } 2613 }
2612 2614
2613 2615
2614 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2616 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2615 ASSERT(args->length() == 0); 2617 ASSERT(args->length() == 0);
2616 2618
2617 Label exit; 2619 Label exit;
2618 // Get the number of formal parameters. 2620 // Get the number of formal parameters.
2619 __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); 2621 __ SafeSet(eax, Immediate(Smi::FromInt(info_->scope()->num_parameters())));
2620 2622
2621 // Check if the calling frame is an arguments adaptor frame. 2623 // Check if the calling frame is an arguments adaptor frame.
2622 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2624 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2623 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), 2625 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset),
2624 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2626 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2625 __ j(not_equal, &exit); 2627 __ j(not_equal, &exit);
2626 2628
2627 // Arguments adaptor case: Read the arguments length from the 2629 // Arguments adaptor case: Read the arguments length from the
2628 // adaptor frame. 2630 // adaptor frame.
2629 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2631 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after
4181 // as their closure, not the anonymous closure containing the global 4183 // as their closure, not the anonymous closure containing the global
4182 // code. Pass a smi sentinel and let the runtime look up the empty 4184 // code. Pass a smi sentinel and let the runtime look up the empty
4183 // function. 4185 // function.
4184 __ push(Immediate(Smi::FromInt(0))); 4186 __ push(Immediate(Smi::FromInt(0)));
4185 } else if (scope()->is_eval_scope()) { 4187 } else if (scope()->is_eval_scope()) {
4186 // Contexts created by a call to eval have the same closure as the 4188 // Contexts created by a call to eval have the same closure as the
4187 // context calling eval, not the anonymous closure containing the eval 4189 // context calling eval, not the anonymous closure containing the eval
4188 // code. Fetch it from the context. 4190 // code. Fetch it from the context.
4189 __ push(ContextOperand(esi, Context::CLOSURE_INDEX)); 4191 __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
4190 } else { 4192 } else {
4191 ASSERT(scope()->is_function_scope()); 4193 ASSERT(scope()->is_function_scope() || scope()->is_catch_scope());
4192 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4194 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4193 } 4195 }
4194 } 4196 }
4195 4197
4196 4198
4197 // ---------------------------------------------------------------------------- 4199 // ----------------------------------------------------------------------------
4198 // Non-local control flow support. 4200 // Non-local control flow support.
4199 4201
4200 void FullCodeGenerator::EnterFinallyBlock() { 4202 void FullCodeGenerator::EnterFinallyBlock() {
4201 // Cook return address on top of stack (smi encoded Code* delta) 4203 // Cook return address on top of stack (smi encoded Code* delta)
4202 ASSERT(!result_register().is(edx)); 4204 ASSERT(!result_register().is(edx));
4203 __ mov(edx, Operand(esp, 0)); 4205 __ pop(edx);
4204 __ sub(Operand(edx), Immediate(masm_->CodeObject())); 4206 __ sub(Operand(edx), Immediate(masm_->CodeObject()));
4205 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4207 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4206 ASSERT_EQ(0, kSmiTag); 4208 ASSERT_EQ(0, kSmiTag);
4207 __ add(edx, Operand(edx)); // Convert to smi. 4209 __ SmiTag(edx);
4208 __ mov(Operand(esp, 0), edx); 4210 __ push(edx);
4209 // Store result register while executing finally block. 4211 // Store result register while executing finally block.
4210 __ push(result_register()); 4212 __ push(result_register());
4211 } 4213 }
4212 4214
4213 4215
4214 void FullCodeGenerator::ExitFinallyBlock() { 4216 void FullCodeGenerator::ExitFinallyBlock() {
4215 ASSERT(!result_register().is(edx)); 4217 ASSERT(!result_register().is(edx));
4216 // Restore result register from stack.
4217 __ pop(result_register()); 4218 __ pop(result_register());
4218 // Uncook return address. 4219 // Uncook return address.
4219 __ mov(edx, Operand(esp, 0)); 4220 __ pop(edx);
4220 __ sar(edx, 1); // Convert smi to int. 4221 __ SmiUntag(edx);
4221 __ add(Operand(edx), Immediate(masm_->CodeObject())); 4222 __ add(Operand(edx), Immediate(masm_->CodeObject()));
4222 __ mov(Operand(esp, 0), edx); 4223 __ jmp(Operand(edx));
4223 // And return.
4224 __ ret(0);
4225 } 4224 }
4226 4225
4227 4226
4228 #undef __ 4227 #undef __
4229 4228
4230 } } // namespace v8::internal 4229 } } // namespace v8::internal
4231 4230
4232 #endif // V8_TARGET_ARCH_IA32 4231 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698