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

Side by Side Diff: src/x64/full-codegen-x64.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 rdi: the JS function object being called (ie, ourselves) 116 // o rdi: the JS function object being called (ie, ourselves)
117 // o rsi: our context 117 // o rsi: our context
118 // o rbp: our caller's frame pointer 118 // o rbp: our caller's frame pointer
119 // o rsp: stack pointer (pointing to return address) 119 // o rsp: 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-x64.h for its layout. 122 // frames-x64.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). rcx is zero for method calls and non-zero for 139 // receiver object). rcx 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 __ testq(rcx, rcx); 143 __ testq(rcx, rcx);
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 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 147 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
147 __ movq(Operand(rsp, receiver_offset), kScratchRegister); 148 __ movq(Operand(rsp, receiver_offset), kScratchRegister);
148 __ bind(&ok); 149 __ bind(&ok);
149 } 150 }
150 151
151 __ push(rbp); // Caller's frame pointer. 152 __ push(rbp); // Caller's frame pointer.
152 __ movq(rbp, rsp); 153 __ movq(rbp, rsp);
153 __ push(rsi); // Callee's context. 154 __ push(rsi); // Callee's context.
154 __ push(rdi); // Callee's JS Function. 155 __ push(rdi); // 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 __ PushRoot(Heap::kUndefinedValueRootIndex); 160 __ PushRoot(Heap::kUndefinedValueRootIndex);
160 } else if (locals_count > 1) { 161 } else if (locals_count > 1) {
161 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 162 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
162 for (int i = 0; i < locals_count; i++) { 163 for (int i = 0; i < locals_count; i++) {
163 __ push(rdx); 164 __ push(rdx);
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 rdi. 175 // Argument to NewContext is the function, which is still in rdi.
175 __ push(rdi); 176 __ push(rdi);
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 rax and rsi. It replaces the context 184 // Context is returned in both rax and rsi. It replaces the context
184 // passed to us. It's saved in the stack and kept live in rsi. 185 // passed to us. It's saved in the stack and kept live in rsi.
185 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 186 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
186 187
187 // Copy any necessary parameters into the context. 188 // Copy any necessary parameters into the context.
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 __ movq(rax, Operand(rbp, parameter_offset)); 196 __ movq(rax, Operand(rbp, 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 __ movq(Operand(rsi, context_offset), rax); 199 __ movq(Operand(rsi, context_offset), rax);
(...skipping 11 matching lines...) Expand all
210 if (arguments != NULL) { 211 if (arguments != NULL) {
211 // Arguments object must be allocated after the context object, in 212 // Arguments object must be allocated after the context object, in
212 // case the "arguments" or ".arguments" variables are in the context. 213 // case the "arguments" or ".arguments" variables are in the context.
213 Comment cmnt(masm_, "[ Allocate arguments object"); 214 Comment cmnt(masm_, "[ Allocate arguments object");
214 if (function_in_register) { 215 if (function_in_register) {
215 __ push(rdi); 216 __ push(rdi);
216 } else { 217 } else {
217 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 218 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
218 } 219 }
219 // The receiver is just before the parameters on the caller's stack. 220 // The receiver is just before the parameters on the caller's stack.
220 int offset = scope()->num_parameters() * kPointerSize; 221 int num_parameters = info->scope()->num_parameters();
222 int offset = num_parameters * kPointerSize;
221 __ lea(rdx, 223 __ lea(rdx,
222 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 224 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
223 __ push(rdx); 225 __ push(rdx);
224 __ Push(Smi::FromInt(scope()->num_parameters())); 226 __ Push(Smi::FromInt(num_parameters));
225 // Arguments to ArgumentsAccessStub: 227 // Arguments to ArgumentsAccessStub:
226 // function, receiver address, parameter count. 228 // function, receiver address, parameter count.
227 // The stub will rewrite receiver and parameter count if the previous 229 // The stub will rewrite receiver and parameter count if the previous
228 // stack frame was an arguments adapter frame. 230 // stack frame was an arguments adapter frame.
229 ArgumentsAccessStub stub( 231 ArgumentsAccessStub stub(
230 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT 232 is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
231 : ArgumentsAccessStub::NEW_NON_STRICT_SLOW); 233 : ArgumentsAccessStub::NEW_NON_STRICT_SLOW);
232 __ CallStub(&stub); 234 __ CallStub(&stub);
233 235
234 Move(arguments->AsSlot(), rax, rbx, rdx); 236 Move(arguments->AsSlot(), rax, rbx, rdx);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 Label check_exit_codesize; 329 Label check_exit_codesize;
328 masm_->bind(&check_exit_codesize); 330 masm_->bind(&check_exit_codesize);
329 #endif 331 #endif
330 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 332 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
331 __ RecordJSReturn(); 333 __ RecordJSReturn();
332 // Do not use the leave instruction here because it is too short to 334 // Do not use the leave instruction here because it is too short to
333 // patch with the code required by the debugger. 335 // patch with the code required by the debugger.
334 __ movq(rsp, rbp); 336 __ movq(rsp, rbp);
335 __ pop(rbp); 337 __ pop(rbp);
336 338
337 int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize; 339 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
338 __ Ret(arguments_bytes, rcx); 340 __ Ret(arguments_bytes, rcx);
339 341
340 #ifdef ENABLE_DEBUGGER_SUPPORT 342 #ifdef ENABLE_DEBUGGER_SUPPORT
341 // Add padding that will be overwritten by a debugger breakpoint. We 343 // Add padding that will be overwritten by a debugger breakpoint. We
342 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k" 344 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
343 // (3 + 1 + 3). 345 // (3 + 1 + 3).
344 const int kPadding = Assembler::kJSReturnSequenceLength - 7; 346 const int kPadding = Assembler::kJSReturnSequenceLength - 7;
345 for (int i = 0; i < kPadding; ++i) { 347 for (int i = 0; i < kPadding; ++i) {
346 masm_->int3(); 348 masm_->int3();
347 } 349 }
(...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, 2020 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2019 int arg_count) { 2021 int arg_count) {
2020 // Push copy of the first argument or undefined if it doesn't exist. 2022 // Push copy of the first argument or undefined if it doesn't exist.
2021 if (arg_count > 0) { 2023 if (arg_count > 0) {
2022 __ push(Operand(rsp, arg_count * kPointerSize)); 2024 __ push(Operand(rsp, arg_count * kPointerSize));
2023 } else { 2025 } else {
2024 __ PushRoot(Heap::kUndefinedValueRootIndex); 2026 __ PushRoot(Heap::kUndefinedValueRootIndex);
2025 } 2027 }
2026 2028
2027 // Push the receiver of the enclosing function and do runtime call. 2029 // Push the receiver of the enclosing function and do runtime call.
2028 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); 2030 __ push(Operand(rbp, (2 + info_->scope()->num_parameters()) * kPointerSize));
2029 2031
2030 // Push the strict mode flag. 2032 // Push the strict mode flag.
2031 __ Push(Smi::FromInt(strict_mode_flag())); 2033 __ Push(Smi::FromInt(strict_mode_flag()));
2032 2034
2033 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP 2035 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2034 ? Runtime::kResolvePossiblyDirectEvalNoLookup 2036 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2035 : Runtime::kResolvePossiblyDirectEval, 4); 2037 : Runtime::kResolvePossiblyDirectEval, 4);
2036 } 2038 }
2037 2039
2038 2040
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2560 } 2562 }
2561 2563
2562 2564
2563 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2565 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2564 ASSERT(args->length() == 1); 2566 ASSERT(args->length() == 1);
2565 2567
2566 // ArgumentsAccessStub expects the key in rdx and the formal 2568 // ArgumentsAccessStub expects the key in rdx and the formal
2567 // parameter count in rax. 2569 // parameter count in rax.
2568 VisitForAccumulatorValue(args->at(0)); 2570 VisitForAccumulatorValue(args->at(0));
2569 __ movq(rdx, rax); 2571 __ movq(rdx, rax);
2570 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2572 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2571 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 2573 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
2572 __ CallStub(&stub); 2574 __ CallStub(&stub);
2573 context()->Plug(rax); 2575 context()->Plug(rax);
2574 } 2576 }
2575 2577
2576 2578
2577 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { 2579 void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
2578 ASSERT(args->length() == 0); 2580 ASSERT(args->length() == 0);
2579 2581
2580 Label exit; 2582 Label exit;
2581 // Get the number of formal parameters. 2583 // Get the number of formal parameters.
2582 __ Move(rax, Smi::FromInt(scope()->num_parameters())); 2584 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
2583 2585
2584 // Check if the calling frame is an arguments adaptor frame. 2586 // Check if the calling frame is an arguments adaptor frame.
2585 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2587 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2586 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 2588 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
2587 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2589 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2588 __ j(not_equal, &exit, Label::kNear); 2590 __ j(not_equal, &exit, Label::kNear);
2589 2591
2590 // Arguments adaptor case: Read the arguments length from the 2592 // Arguments adaptor case: Read the arguments length from the
2591 // adaptor frame. 2593 // adaptor frame.
2592 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2594 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
(...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 // as their closure, not the anonymous closure containing the global 4161 // as their closure, not the anonymous closure containing the global
4160 // code. Pass a smi sentinel and let the runtime look up the empty 4162 // code. Pass a smi sentinel and let the runtime look up the empty
4161 // function. 4163 // function.
4162 __ Push(Smi::FromInt(0)); 4164 __ Push(Smi::FromInt(0));
4163 } else if (scope()->is_eval_scope()) { 4165 } else if (scope()->is_eval_scope()) {
4164 // Contexts created by a call to eval have the same closure as the 4166 // Contexts created by a call to eval have the same closure as the
4165 // context calling eval, not the anonymous closure containing the eval 4167 // context calling eval, not the anonymous closure containing the eval
4166 // code. Fetch it from the context. 4168 // code. Fetch it from the context.
4167 __ push(ContextOperand(rsi, Context::CLOSURE_INDEX)); 4169 __ push(ContextOperand(rsi, Context::CLOSURE_INDEX));
4168 } else { 4170 } else {
4169 ASSERT(scope()->is_function_scope()); 4171 ASSERT(scope()->is_function_scope() || scope()->is_catch_scope());
4170 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4172 __ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4171 } 4173 }
4172 } 4174 }
4173 4175
4174 4176
4175 // ---------------------------------------------------------------------------- 4177 // ----------------------------------------------------------------------------
4176 // Non-local control flow support. 4178 // Non-local control flow support.
4177 4179
4178 4180
4179 void FullCodeGenerator::EnterFinallyBlock() { 4181 void FullCodeGenerator::EnterFinallyBlock() {
4180 ASSERT(!result_register().is(rdx)); 4182 ASSERT(!result_register().is(rdx));
4181 ASSERT(!result_register().is(rcx)); 4183 ASSERT(!result_register().is(rcx));
4182 // Cook return address on top of stack (smi encoded Code* delta) 4184 // Cook return address on top of stack (smi encoded Code* delta)
4183 __ movq(rdx, Operand(rsp, 0)); 4185 __ pop(rdx);
4184 __ Move(rcx, masm_->CodeObject()); 4186 __ Move(rcx, masm_->CodeObject());
4185 __ subq(rdx, rcx); 4187 __ subq(rdx, rcx);
4186 __ Integer32ToSmi(rdx, rdx); 4188 __ Integer32ToSmi(rdx, rdx);
4187 __ movq(Operand(rsp, 0), rdx); 4189 __ push(rdx);
4188 // Store result register while executing finally block. 4190 // Store result register while executing finally block.
4189 __ push(result_register()); 4191 __ push(result_register());
4190 } 4192 }
4191 4193
4192 4194
4193 void FullCodeGenerator::ExitFinallyBlock() { 4195 void FullCodeGenerator::ExitFinallyBlock() {
4194 ASSERT(!result_register().is(rdx)); 4196 ASSERT(!result_register().is(rdx));
4195 ASSERT(!result_register().is(rcx)); 4197 ASSERT(!result_register().is(rcx));
4196 // Restore result register from stack.
4197 __ pop(result_register()); 4198 __ pop(result_register());
4198 // Uncook return address. 4199 // Uncook return address.
4199 __ movq(rdx, Operand(rsp, 0)); 4200 __ pop(rdx);
4200 __ SmiToInteger32(rdx, rdx); 4201 __ SmiToInteger32(rdx, rdx);
4201 __ Move(rcx, masm_->CodeObject()); 4202 __ Move(rcx, masm_->CodeObject());
4202 __ addq(rdx, rcx); 4203 __ addq(rdx, rcx);
4203 __ movq(Operand(rsp, 0), rdx); 4204 __ jmp(rdx);
4204 // And return.
4205 __ ret(0);
4206 } 4205 }
4207 4206
4208 4207
4209 #undef __ 4208 #undef __
4210 4209
4211 4210
4212 } } // namespace v8::internal 4211 } } // namespace v8::internal
4213 4212
4214 #endif // V8_TARGET_ARCH_X64 4213 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698