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

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