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

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

Issue 14843020: Unify deoptimizer for JavaScript frames. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 7 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
« no previous file with comments | « no previous file | src/arm/frames-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 if (FLAG_trace_osr) { 369 if (FLAG_trace_osr) {
370 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", 370 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
371 ok ? "finished" : "aborted", 371 ok ? "finished" : "aborted",
372 reinterpret_cast<intptr_t>(function_)); 372 reinterpret_cast<intptr_t>(function_));
373 function_->PrintName(); 373 function_->PrintName();
374 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); 374 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc());
375 } 375 }
376 } 376 }
377 377
378 378
379 // This code is very similar to ia32 code, but relies on register names (fp, sp)
380 // and how the frame is laid out.
381 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
382 int frame_index) {
383 // Read the ast node id, function, and frame height for this output frame.
384 BailoutId node_id = BailoutId(iterator->Next());
385 JSFunction* function;
386 if (frame_index != 0) {
387 function = JSFunction::cast(ComputeLiteral(iterator->Next()));
388 } else {
389 int closure_id = iterator->Next();
390 USE(closure_id);
391 ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
392 function = function_;
393 }
394 unsigned height = iterator->Next();
395 unsigned height_in_bytes = height * kPointerSize;
396 if (trace_) {
397 PrintF(" translating ");
398 function->PrintName();
399 PrintF(" => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
400 }
401
402 // The 'fixed' part of the frame consists of the incoming parameters and
403 // the part described by JavaScriptFrameConstants.
404 unsigned fixed_frame_size = ComputeFixedSize(function);
405 unsigned input_frame_size = input_->GetFrameSize();
406 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
407
408 // Allocate and store the output frame description.
409 FrameDescription* output_frame =
410 new(output_frame_size) FrameDescription(output_frame_size, function);
411 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
412
413 bool is_bottommost = (0 == frame_index);
414 bool is_topmost = (output_count_ - 1 == frame_index);
415 ASSERT(frame_index >= 0 && frame_index < output_count_);
416 ASSERT(output_[frame_index] == NULL);
417 output_[frame_index] = output_frame;
418
419 // The top address for the bottommost output frame can be computed from
420 // the input frame pointer and the output frame's height. For all
421 // subsequent output frames, it can be computed from the previous one's
422 // top address and the current frame's size.
423 uint32_t top_address;
424 if (is_bottommost) {
425 // 2 = context and function in the frame.
426 top_address =
427 input_->GetRegister(fp.code()) - (2 * kPointerSize) - height_in_bytes;
428 } else {
429 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
430 }
431 output_frame->SetTop(top_address);
432
433 // Compute the incoming parameter translation.
434 int parameter_count = function->shared()->formal_parameter_count() + 1;
435 unsigned output_offset = output_frame_size;
436 unsigned input_offset = input_frame_size;
437 for (int i = 0; i < parameter_count; ++i) {
438 output_offset -= kPointerSize;
439 DoTranslateCommand(iterator, frame_index, output_offset);
440 }
441 input_offset -= (parameter_count * kPointerSize);
442
443 // There are no translation commands for the caller's pc and fp, the
444 // context, and the function. Synthesize their values and set them up
445 // explicitly.
446 //
447 // The caller's pc for the bottommost output frame is the same as in the
448 // input frame. For all subsequent output frames, it can be read from the
449 // previous one. This frame's pc can be computed from the non-optimized
450 // function code and AST id of the bailout.
451 output_offset -= kPointerSize;
452 input_offset -= kPointerSize;
453 intptr_t value;
454 if (is_bottommost) {
455 value = input_->GetFrameSlot(input_offset);
456 } else {
457 value = output_[frame_index - 1]->GetPc();
458 }
459 output_frame->SetFrameSlot(output_offset, value);
460 if (trace_) {
461 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
462 top_address + output_offset, output_offset, value);
463 }
464
465 // The caller's frame pointer for the bottommost output frame is the same
466 // as in the input frame. For all subsequent output frames, it can be
467 // read from the previous one. Also compute and set this frame's frame
468 // pointer.
469 output_offset -= kPointerSize;
470 input_offset -= kPointerSize;
471 if (is_bottommost) {
472 value = input_->GetFrameSlot(input_offset);
473 } else {
474 value = output_[frame_index - 1]->GetFp();
475 }
476 output_frame->SetFrameSlot(output_offset, value);
477 intptr_t fp_value = top_address + output_offset;
478 ASSERT(!is_bottommost || input_->GetRegister(fp.code()) == fp_value);
479 output_frame->SetFp(fp_value);
480 if (is_topmost) {
481 output_frame->SetRegister(fp.code(), fp_value);
482 }
483 if (trace_) {
484 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
485 fp_value, output_offset, value);
486 }
487
488 // For the bottommost output frame the context can be gotten from the input
489 // frame. For all subsequent output frames it can be gotten from the function
490 // so long as we don't inline functions that need local contexts.
491 output_offset -= kPointerSize;
492 input_offset -= kPointerSize;
493 if (is_bottommost) {
494 value = input_->GetFrameSlot(input_offset);
495 } else {
496 value = reinterpret_cast<intptr_t>(function->context());
497 }
498 output_frame->SetFrameSlot(output_offset, value);
499 output_frame->SetContext(value);
500 if (is_topmost) output_frame->SetRegister(cp.code(), value);
501 if (trace_) {
502 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n",
503 top_address + output_offset, output_offset, value);
504 }
505
506 // The function was mentioned explicitly in the BEGIN_FRAME.
507 output_offset -= kPointerSize;
508 input_offset -= kPointerSize;
509 value = reinterpret_cast<uint32_t>(function);
510 // The function for the bottommost output frame should also agree with the
511 // input frame.
512 ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
513 output_frame->SetFrameSlot(output_offset, value);
514 if (trace_) {
515 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
516 top_address + output_offset, output_offset, value);
517 }
518
519 // Translate the rest of the frame.
520 for (unsigned i = 0; i < height; ++i) {
521 output_offset -= kPointerSize;
522 DoTranslateCommand(iterator, frame_index, output_offset);
523 }
524 ASSERT(0 == output_offset);
525
526 // Compute this frame's PC, state, and continuation.
527 Code* non_optimized_code = function->shared()->code();
528 FixedArray* raw_data = non_optimized_code->deoptimization_data();
529 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
530 Address start = non_optimized_code->instruction_start();
531 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
532 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
533 uint32_t pc_value = reinterpret_cast<uint32_t>(start + pc_offset);
534 output_frame->SetPc(pc_value);
535 if (is_topmost) {
536 output_frame->SetRegister(pc.code(), pc_value);
537 }
538
539 FullCodeGenerator::State state =
540 FullCodeGenerator::StateField::decode(pc_and_state);
541 output_frame->SetState(Smi::FromInt(state));
542
543
544 // Set the continuation for the topmost frame.
545 if (is_topmost && bailout_type_ != DEBUGGER) {
546 Builtins* builtins = isolate_->builtins();
547 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
548 if (bailout_type_ == LAZY) {
549 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
550 } else if (bailout_type_ == SOFT) {
551 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
552 } else {
553 ASSERT(bailout_type_ == EAGER);
554 }
555 output_frame->SetContinuation(
556 reinterpret_cast<uint32_t>(continuation->entry()));
557 }
558 }
559
560
561 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { 379 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
562 // Set the register values. The values are not important as there are no 380 // Set the register values. The values are not important as there are no
563 // callee saved registers in JavaScript frames, so all registers are 381 // callee saved registers in JavaScript frames, so all registers are
564 // spilled. Registers fp and sp are set to the correct values though. 382 // spilled. Registers fp and sp are set to the correct values though.
565 383
566 for (int i = 0; i < Register::kNumRegisters; i++) { 384 for (int i = 0; i < Register::kNumRegisters; i++) {
567 input_->SetRegister(i, i * 4); 385 input_->SetRegister(i, i * 4);
568 } 386 }
569 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); 387 input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
570 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); 388 input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
(...skipping 23 matching lines...) Expand all
594 412
595 413
596 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { 414 void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
597 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) { 415 for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
598 double double_value = input_->GetDoubleRegister(i); 416 double double_value = input_->GetDoubleRegister(i);
599 output_frame->SetDoubleRegister(i, double_value); 417 output_frame->SetDoubleRegister(i, double_value);
600 } 418 }
601 } 419 }
602 420
603 421
422 bool Deoptimizer::HasAlignmentPadding(JSFunction* function) {
423 // There is no dynamic alignment padding on ARM in the input frame.
424 return false;
425 }
426
427
604 #define __ masm()-> 428 #define __ masm()->
605 429
606 // This code tries to be close to ia32 code so that any changes can be 430 // This code tries to be close to ia32 code so that any changes can be
607 // easily ported. 431 // easily ported.
608 void Deoptimizer::EntryGenerator::Generate() { 432 void Deoptimizer::EntryGenerator::Generate() {
609 GeneratePrologue(); 433 GeneratePrologue();
610 434
611 // Save all general purpose registers before messing with them. 435 // Save all general purpose registers before messing with them.
612 const int kNumberOfRegisters = Register::kNumRegisters; 436 const int kNumberOfRegisters = Register::kNumRegisters;
613 437
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 __ push(ip); 652 __ push(ip);
829 __ b(&done); 653 __ b(&done);
830 ASSERT(masm()->pc_offset() - start == table_entry_size_); 654 ASSERT(masm()->pc_offset() - start == table_entry_size_);
831 } 655 }
832 __ bind(&done); 656 __ bind(&done);
833 } 657 }
834 658
835 #undef __ 659 #undef __
836 660
837 } } // namespace v8::internal 661 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/arm/frames-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698