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

Side by Side Diff: src/x64/deoptimizer-x64.cc

Issue 21340002: Generate a custom OSR entrypoint for OSR compiles on all platforms, and transition to optimized cod… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 4 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 ASSERT_EQ(interrupt_code->entry(), 161 ASSERT_EQ(interrupt_code->entry(),
162 Assembler::target_address_at(call_target_address)); 162 Assembler::target_address_at(call_target_address));
163 ASSERT_EQ(kJnsInstruction, *(call_target_address - 3)); 163 ASSERT_EQ(kJnsInstruction, *(call_target_address - 3));
164 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); 164 ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
165 return false; 165 return false;
166 } 166 }
167 } 167 }
168 #endif // DEBUG 168 #endif // DEBUG
169 169
170 170
171 static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) {
172 ByteArray* translations = data->TranslationByteArray();
173 int length = data->DeoptCount();
174 for (int i = 0; i < length; i++) {
175 if (data->AstId(i) == ast_id) {
176 TranslationIterator it(translations, data->TranslationIndex(i)->value());
177 int value = it.Next();
178 ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value));
179 // Read the number of frames.
180 value = it.Next();
181 if (value == 1) return i;
182 }
183 }
184 UNREACHABLE();
185 return -1;
186 }
187
188
189 void Deoptimizer::DoComputeOsrOutputFrame() {
190 DeoptimizationInputData* data = DeoptimizationInputData::cast(
191 compiled_code_->deoptimization_data());
192 unsigned ast_id = data->OsrAstId()->value();
193 // TODO(kasperl): This should not be the bailout_id_. It should be
194 // the ast id. Confusing.
195 ASSERT(bailout_id_ == ast_id);
196
197 int bailout_id = LookupBailoutId(data, BailoutId(ast_id));
198 unsigned translation_index = data->TranslationIndex(bailout_id)->value();
199 ByteArray* translations = data->TranslationByteArray();
200
201 TranslationIterator iterator(translations, translation_index);
202 Translation::Opcode opcode =
203 static_cast<Translation::Opcode>(iterator.Next());
204 ASSERT(Translation::BEGIN == opcode);
205 USE(opcode);
206 int count = iterator.Next();
207 iterator.Skip(1); // Drop JS frame count.
208 ASSERT(count == 1);
209 USE(count);
210
211 opcode = static_cast<Translation::Opcode>(iterator.Next());
212 USE(opcode);
213 ASSERT(Translation::JS_FRAME == opcode);
214 unsigned node_id = iterator.Next();
215 USE(node_id);
216 ASSERT(node_id == ast_id);
217 int closure_id = iterator.Next();
218 USE(closure_id);
219 ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
220 unsigned height = iterator.Next();
221 unsigned height_in_bytes = height * kPointerSize;
222 USE(height_in_bytes);
223
224 unsigned fixed_size = ComputeFixedSize(function_);
225 unsigned input_frame_size = input_->GetFrameSize();
226 ASSERT(fixed_size + height_in_bytes == input_frame_size);
227
228 unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize;
229 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value();
230 unsigned outgoing_size = outgoing_height * kPointerSize;
231 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size;
232 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call.
233
234 if (FLAG_trace_osr) {
235 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
236 reinterpret_cast<intptr_t>(function_));
237 PrintFunctionName();
238 PrintF(" => node=%u, frame=%d->%d]\n",
239 ast_id,
240 input_frame_size,
241 output_frame_size);
242 }
243
244 // There's only one output frame in the OSR case.
245 output_count_ = 1;
246 output_ = new FrameDescription*[1];
247 output_[0] = new(output_frame_size) FrameDescription(
248 output_frame_size, function_);
249 output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
250
251 // Clear the incoming parameters in the optimized frame to avoid
252 // confusing the garbage collector.
253 unsigned output_offset = output_frame_size - kPointerSize;
254 int parameter_count = function_->shared()->formal_parameter_count() + 1;
255 for (int i = 0; i < parameter_count; ++i) {
256 output_[0]->SetFrameSlot(output_offset, 0);
257 output_offset -= kPointerSize;
258 }
259
260 // Translate the incoming parameters. This may overwrite some of the
261 // incoming argument slots we've just cleared.
262 int input_offset = input_frame_size - kPointerSize;
263 bool ok = true;
264 int limit = input_offset - (parameter_count * kPointerSize);
265 while (ok && input_offset > limit) {
266 ok = DoOsrTranslateCommand(&iterator, &input_offset);
267 }
268
269 // There are no translation commands for the caller's pc and fp, the
270 // context, and the function. Set them up explicitly.
271 for (int i = StandardFrameConstants::kCallerPCOffset;
272 ok && i >= StandardFrameConstants::kMarkerOffset;
273 i -= kPointerSize) {
274 intptr_t input_value = input_->GetFrameSlot(input_offset);
275 if (FLAG_trace_osr) {
276 const char* name = "UNKNOWN";
277 switch (i) {
278 case StandardFrameConstants::kCallerPCOffset:
279 name = "caller's pc";
280 break;
281 case StandardFrameConstants::kCallerFPOffset:
282 name = "fp";
283 break;
284 case StandardFrameConstants::kContextOffset:
285 name = "context";
286 break;
287 case StandardFrameConstants::kMarkerOffset:
288 name = "function";
289 break;
290 }
291 PrintF(" [rsp + %d] <- 0x%08" V8PRIxPTR " ; [rsp + %d] "
292 "(fixed part - %s)\n",
293 output_offset,
294 input_value,
295 input_offset,
296 name);
297 }
298 output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
299 input_offset -= kPointerSize;
300 output_offset -= kPointerSize;
301 }
302
303 // Translate the rest of the frame.
304 while (ok && input_offset >= 0) {
305 ok = DoOsrTranslateCommand(&iterator, &input_offset);
306 }
307
308 // If translation of any command failed, continue using the input frame.
309 if (!ok) {
310 delete output_[0];
311 output_[0] = input_;
312 output_[0]->SetPc(reinterpret_cast<intptr_t>(from_));
313 } else {
314 // Set up the frame pointer and the context pointer.
315 output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code()));
316 output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code()));
317
318 unsigned pc_offset = data->OsrPcOffset()->value();
319 intptr_t pc = reinterpret_cast<intptr_t>(
320 compiled_code_->entry() + pc_offset);
321 output_[0]->SetPc(pc);
322 }
323 Code* continuation =
324 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR);
325 output_[0]->SetContinuation(
326 reinterpret_cast<intptr_t>(continuation->entry()));
327
328 if (FLAG_trace_osr) {
329 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
330 ok ? "finished" : "aborted",
331 reinterpret_cast<intptr_t>(function_));
332 PrintFunctionName();
333 PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc());
334 }
335 }
336
337
338 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { 171 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
339 // Set the register values. The values are not important as there are no 172 // Set the register values. The values are not important as there are no
340 // callee saved registers in JavaScript frames, so all registers are 173 // callee saved registers in JavaScript frames, so all registers are
341 // spilled. Registers rbp and rsp are set to the correct values though. 174 // spilled. Registers rbp and rsp are set to the correct values though.
342 for (int i = 0; i < Register::kNumRegisters; i++) { 175 for (int i = 0; i < Register::kNumRegisters; i++) {
343 input_->SetRegister(i, i * 4); 176 input_->SetRegister(i, i * 4);
344 } 177 }
345 input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp())); 178 input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp()));
346 input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp())); 179 input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp()));
347 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { 180 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 __ cmpq(rax, rdx); 357 __ cmpq(rax, rdx);
525 __ j(below, &outer_push_loop); 358 __ j(below, &outer_push_loop);
526 359
527 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) { 360 for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
528 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); 361 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
529 int src_offset = i * kDoubleSize + double_regs_offset; 362 int src_offset = i * kDoubleSize + double_regs_offset;
530 __ movsd(xmm_reg, Operand(rbx, src_offset)); 363 __ movsd(xmm_reg, Operand(rbx, src_offset));
531 } 364 }
532 365
533 // Push state, pc, and continuation from the last output frame. 366 // Push state, pc, and continuation from the last output frame.
534 if (type() != OSR) { 367 __ push(Operand(rbx, FrameDescription::state_offset()));
535 __ push(Operand(rbx, FrameDescription::state_offset()));
536 }
537 __ push(Operand(rbx, FrameDescription::pc_offset())); 368 __ push(Operand(rbx, FrameDescription::pc_offset()));
538 __ push(Operand(rbx, FrameDescription::continuation_offset())); 369 __ push(Operand(rbx, FrameDescription::continuation_offset()));
539 370
540 // Push the registers from the last output frame. 371 // Push the registers from the last output frame.
541 for (int i = 0; i < kNumberOfRegisters; i++) { 372 for (int i = 0; i < kNumberOfRegisters; i++) {
542 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 373 int offset = (i * kPointerSize) + FrameDescription::registers_offset();
543 __ push(Operand(rbx, offset)); 374 __ push(Operand(rbx, offset));
544 } 375 }
545 376
546 // Restore the registers from the stack. 377 // Restore the registers from the stack.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 SetFrameSlot(offset, value); 418 SetFrameSlot(offset, value);
588 } 419 }
589 420
590 421
591 #undef __ 422 #undef __
592 423
593 424
594 } } // namespace v8::internal 425 } } // namespace v8::internal
595 426
596 #endif // V8_TARGET_ARCH_X64 427 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/runtime.cc ('K') | « src/x64/builtins-x64.cc ('k') | src/x64/lithium-codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698