1// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "hydrogen.h"
29#include "hydrogen-osr.h"
30
31namespace v8 {
32namespace internal {
33
34// True iff. we are compiling for OSR and the statement is the entry.
35bool HOsrBuilder::HasOsrEntryAt(IterationStatement* statement) {
36  return statement->OsrEntryId() == builder_->current_info()->osr_ast_id();
37}
38
39
40// Build a new loop header block and set it as the current block.
41HBasicBlock *HOsrBuilder::BuildLoopEntry() {
42  HBasicBlock* loop_entry = builder_->CreateLoopHeaderBlock();
43  builder_->current_block()->Goto(loop_entry);
44  builder_->set_current_block(loop_entry);
45  return loop_entry;
46}
47
48
49HBasicBlock* HOsrBuilder::BuildPossibleOsrLoopEntry(
50    IterationStatement* statement) {
51  // Check if there is an OSR here first.
52  if (!HasOsrEntryAt(statement)) return BuildLoopEntry();
53
54  Zone* zone = builder_->zone();
55  HGraph* graph = builder_->graph();
56
57  // only one OSR point per compile is allowed.
58  ASSERT(graph->osr() == NULL);
59
60  // remember this builder as the one OSR builder in the graph.
61  graph->set_osr(this);
62
63  HBasicBlock* non_osr_entry = graph->CreateBasicBlock();
64  osr_entry_ = graph->CreateBasicBlock();
65  HValue* true_value = graph->GetConstantTrue();
66  HBranch* test = new(zone) HBranch(true_value, ToBooleanStub::Types(),
67                                    non_osr_entry, osr_entry_);
68  builder_->current_block()->Finish(test);
69
70  HBasicBlock* loop_predecessor = graph->CreateBasicBlock();
71  non_osr_entry->Goto(loop_predecessor);
72
73  builder_->set_current_block(osr_entry_);
74  osr_entry_->set_osr_entry();
75  BailoutId osr_entry_id = statement->OsrEntryId();
76
77  HEnvironment *environment = builder_->environment();
78  int first_expression_index = environment->first_expression_index();
79  int length = environment->length();
80  osr_values_ = new(zone) ZoneList<HUnknownOSRValue*>(length, zone);
81
82  for (int i = 0; i < first_expression_index; ++i) {
83    HUnknownOSRValue* osr_value = builder_->Add<HUnknownOSRValue>();
84    environment->Bind(i, osr_value);
85    osr_values_->Add(osr_value, zone);
86  }
87
88  if (first_expression_index != length) {
89    environment->Drop(length - first_expression_index);
90    for (int i = first_expression_index; i < length; ++i) {
91      HUnknownOSRValue* osr_value = builder_->Add<HUnknownOSRValue>();
92      environment->Push(osr_value);
93      osr_values_->Add(osr_value, zone);
94    }
95  }
96
97  builder_->Add<HSimulate>(osr_entry_id);
98  builder_->Add<HOsrEntry>(osr_entry_id);
99  HContext* context = builder_->Add<HContext>();
100  environment->BindContext(context);
101  builder_->current_block()->Goto(loop_predecessor);
102  loop_predecessor->SetJoinId(statement->EntryId());
103  builder_->set_current_block(loop_predecessor);
104
105  // Create the final loop entry
106  osr_loop_entry_ = BuildLoopEntry();
107  return osr_loop_entry_;
108}
109
110
111void HOsrBuilder::FinishGraph() {
112  // do nothing for now.
113}
114
115
116void HOsrBuilder::FinishOsrValues() {
117  const ZoneList<HPhi*>* phis = osr_loop_entry_->phis();
118  for (int j = 0; j < phis->length(); j++) {
119    HPhi* phi = phis->at(j);
120    ASSERT(phi->HasMergedIndex());
121    osr_values_->at(phi->merged_index())->set_incoming_value(phi);
122  }
123}
124
125} }  // namespace v8::internal
126