V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
cfg.cc
1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/torque/cfg.h"
6 
7 #include "src/torque/type-oracle.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace torque {
12 
13 void Block::SetInputTypes(const Stack<const Type*>& input_types) {
14  if (!input_types_) {
15  input_types_ = input_types;
16  return;
17  } else if (*input_types_ == input_types) {
18  return;
19  }
20 
21  DCHECK_EQ(input_types.Size(), input_types_->Size());
22  Stack<const Type*> merged_types;
23  bool widened = false;
24  auto c2_iterator = input_types.begin();
25  for (const Type* c1 : *input_types_) {
26  const Type* merged_type = TypeOracle::GetUnionType(c1, *c2_iterator++);
27  if (!merged_type->IsSubtypeOf(c1)) {
28  widened = true;
29  }
30  merged_types.Push(merged_type);
31  }
32  if (merged_types.Size() == input_types_->Size()) {
33  if (widened) {
34  input_types_ = merged_types;
35  Retype();
36  }
37  return;
38  }
39 
40  std::stringstream error;
41  error << "incompatible types at branch:\n";
42  for (intptr_t i = std::max(input_types_->Size(), input_types.Size()) - 1;
43  i >= 0; --i) {
44  base::Optional<const Type*> left;
45  base::Optional<const Type*> right;
46  if (static_cast<size_t>(i) < input_types.Size()) {
47  left = input_types.Peek(BottomOffset{static_cast<size_t>(i)});
48  }
49  if (static_cast<size_t>(i) < input_types_->Size()) {
50  right = input_types_->Peek(BottomOffset{static_cast<size_t>(i)});
51  }
52  if (left && right && *left == *right) {
53  error << **left << "\n";
54  } else {
55  if (left) {
56  error << **left;
57  } else {
58  error << "/*missing*/";
59  }
60  error << " => ";
61  if (right) {
62  error << **right;
63  } else {
64  error << "/*missing*/";
65  }
66  error << "\n";
67  }
68  }
69  ReportError(error.str());
70 }
71 
72 void CfgAssembler::Bind(Block* block) {
73  DCHECK(current_block_->IsComplete());
74  DCHECK(block->instructions().empty());
75  DCHECK(block->HasInputTypes());
76  current_block_ = block;
77  current_stack_ = block->InputTypes();
78  cfg_.PlaceBlock(block);
79 }
80 
81 void CfgAssembler::Goto(Block* block) {
82  if (block->HasInputTypes()) {
83  DropTo(block->InputTypes().AboveTop());
84  }
85  Emit(GotoInstruction{block});
86 }
87 
88 StackRange CfgAssembler::Goto(Block* block, size_t preserved_slots) {
89  DCHECK(block->HasInputTypes());
90  DCHECK_GE(CurrentStack().Size(), block->InputTypes().Size());
91  Emit(DeleteRangeInstruction{
92  StackRange{block->InputTypes().AboveTop() - preserved_slots,
93  CurrentStack().AboveTop() - preserved_slots}});
94  StackRange preserved_slot_range = TopRange(preserved_slots);
95  Emit(GotoInstruction{block});
96  return preserved_slot_range;
97 }
98 
99 void CfgAssembler::Branch(Block* if_true, Block* if_false) {
100  Emit(BranchInstruction{if_true, if_false});
101 }
102 
103 // Delete the specified range of slots, moving upper slots to fill the gap.
104 void CfgAssembler::DeleteRange(StackRange range) {
105  DCHECK_LE(range.end(), current_stack_.AboveTop());
106  if (range.Size() == 0) return;
107  Emit(DeleteRangeInstruction{range});
108 }
109 
110 void CfgAssembler::DropTo(BottomOffset new_level) {
111  DeleteRange(StackRange{new_level, CurrentStack().AboveTop()});
112 }
113 
114 StackRange CfgAssembler::Peek(StackRange range,
115  base::Optional<const Type*> type) {
116  std::vector<const Type*> lowered_types;
117  if (type) {
118  lowered_types = LowerType(*type);
119  DCHECK_EQ(lowered_types.size(), range.Size());
120  }
121  for (size_t i = 0; i < range.Size(); ++i) {
122  Emit(PeekInstruction{
123  range.begin() + i,
124  type ? lowered_types[i] : base::Optional<const Type*>{}});
125  }
126  return TopRange(range.Size());
127 }
128 
129 void CfgAssembler::Poke(StackRange destination, StackRange origin,
130  base::Optional<const Type*> type) {
131  DCHECK_EQ(destination.Size(), origin.Size());
132  DCHECK_LE(destination.end(), origin.begin());
133  DCHECK_EQ(origin.end(), CurrentStack().AboveTop());
134  std::vector<const Type*> lowered_types;
135  if (type) {
136  lowered_types = LowerType(*type);
137  DCHECK_EQ(lowered_types.size(), origin.Size());
138  }
139  for (intptr_t i = origin.Size() - 1; i >= 0; --i) {
140  Emit(PokeInstruction{
141  destination.begin() + i,
142  type ? lowered_types[i] : base::Optional<const Type*>{}});
143  }
144 }
145 
146 void CfgAssembler::Print(std::string s) {
147  Emit(PrintConstantStringInstruction{std::move(s)});
148 }
149 
150 void CfgAssembler::AssertionFailure(std::string message) {
151  Emit(AbortInstruction{AbortInstruction::Kind::kAssertionFailure,
152  std::move(message)});
153 }
154 
155 void CfgAssembler::Unreachable() {
156  Emit(AbortInstruction{AbortInstruction::Kind::kUnreachable});
157 }
158 
159 void CfgAssembler::DebugBreak() {
160  Emit(AbortInstruction{AbortInstruction::Kind::kDebugBreak});
161 }
162 
163 } // namespace torque
164 } // namespace internal
165 } // namespace v8
Definition: libplatform.h:13