V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
instructions.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/instructions.h"
6 #include "src/torque/cfg.h"
7 #include "src/torque/type-oracle.h"
8 
9 namespace v8 {
10 namespace internal {
11 namespace torque {
12 
13 #define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name) \
14  const InstructionKind Name::kKind = InstructionKind::k##Name; \
15  std::unique_ptr<InstructionBase> Name::Clone() const { \
16  return std::unique_ptr<InstructionBase>(new Name(*this)); \
17  } \
18  void Name::Assign(const InstructionBase& other) { \
19  *this = static_cast<const Name&>(other); \
20  }
21 TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
22 #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
23 
24 void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
25  ControlFlowGraph* cfg) const {
26  const Type* type = stack->Peek(slot);
27  if (widened_type) {
28  if (type->IsTopType()) {
29  const TopType* top_type = TopType::cast(type);
30  ReportError("use of " + top_type->reason());
31  }
32  if (!type->IsSubtypeOf(*widened_type)) {
33  ReportError("type ", *type, " is not a subtype of ", **widened_type);
34  }
35  type = *widened_type;
36  }
37  stack->Push(type);
38 }
39 
40 void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
41  ControlFlowGraph* cfg) const {
42  const Type* type = stack->Top();
43  if (widened_type) {
44  if (!type->IsSubtypeOf(*widened_type)) {
45  ReportError("type ", type, " is not a subtype of ", *widened_type);
46  }
47  type = *widened_type;
48  }
49  stack->Poke(slot, type);
50  stack->Pop();
51 }
52 
53 void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack,
54  ControlFlowGraph* cfg) const {
55  stack->DeleteRange(range);
56 }
57 
58 void PushUninitializedInstruction::TypeInstruction(
59  Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
60  stack->Push(type);
61 }
62 
63 void PushCodePointerInstruction::TypeInstruction(Stack<const Type*>* stack,
64  ControlFlowGraph* cfg) const {
65  stack->Push(type);
66 }
67 
68 void NamespaceConstantInstruction::TypeInstruction(
69  Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
70  stack->PushMany(LowerType(constant->type()));
71 }
72 
73 void InstructionBase::InvalidateTransientTypes(
74  Stack<const Type*>* stack) const {
75  auto current = stack->begin();
76  while (current != stack->end()) {
77  if ((*current)->IsTransient()) {
78  std::stringstream stream;
79  stream << "type " << **current
80  << " is made invalid by transitioning callable invocation at "
81  << PositionAsString(pos);
82  *current = TypeOracle::GetTopType(stream.str(), *current);
83  }
84  ++current;
85  }
86 }
87 
88 void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
89  ControlFlowGraph* cfg) const {
90  std::vector<const Type*> parameter_types =
91  LowerParameterTypes(intrinsic->signature().parameter_types);
92  for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
93  const Type* arg_type = stack->Pop();
94  const Type* parameter_type = parameter_types.back();
95  parameter_types.pop_back();
96  if (arg_type != parameter_type) {
97  ReportError("parameter ", i, ": expected type ", *parameter_type,
98  " but found type ", *arg_type);
99  }
100  }
101  if (intrinsic->IsTransitioning()) {
102  InvalidateTransientTypes(stack);
103  }
104  stack->PushMany(LowerType(intrinsic->signature().return_type));
105 }
106 
107 void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
108  ControlFlowGraph* cfg) const {
109  std::vector<const Type*> parameter_types =
110  LowerParameterTypes(macro->signature().parameter_types);
111  for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
112  const Type* arg_type = stack->Pop();
113  const Type* parameter_type = parameter_types.back();
114  parameter_types.pop_back();
115  if (arg_type != parameter_type) {
116  ReportError("parameter ", i, ": expected type ", *parameter_type,
117  " but found type ", *arg_type);
118  }
119  }
120 
121  if (macro->IsTransitioning()) {
122  InvalidateTransientTypes(stack);
123  }
124 
125  if (catch_block) {
126  Stack<const Type*> catch_stack = *stack;
127  catch_stack.Push(TypeOracle::GetObjectType());
128  (*catch_block)->SetInputTypes(catch_stack);
129  }
130 
131  stack->PushMany(LowerType(macro->signature().return_type));
132 }
133 
134 void CallCsaMacroAndBranchInstruction::TypeInstruction(
135  Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
136  std::vector<const Type*> parameter_types =
137  LowerParameterTypes(macro->signature().parameter_types);
138  for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
139  const Type* arg_type = stack->Pop();
140  const Type* parameter_type = parameter_types.back();
141  parameter_types.pop_back();
142  if (arg_type != parameter_type) {
143  ReportError("parameter ", i, ": expected type ", *parameter_type,
144  " but found type ", *arg_type);
145  }
146  }
147 
148  if (label_blocks.size() != macro->signature().labels.size()) {
149  ReportError("wrong number of labels");
150  }
151  for (size_t i = 0; i < label_blocks.size(); ++i) {
152  Stack<const Type*> continuation_stack = *stack;
153  continuation_stack.PushMany(
154  LowerParameterTypes(macro->signature().labels[i].types));
155  label_blocks[i]->SetInputTypes(std::move(continuation_stack));
156  }
157 
158  if (macro->IsTransitioning()) {
159  InvalidateTransientTypes(stack);
160  }
161 
162  if (catch_block) {
163  Stack<const Type*> catch_stack = *stack;
164  catch_stack.Push(TypeOracle::GetObjectType());
165  (*catch_block)->SetInputTypes(catch_stack);
166  }
167 
168  if (macro->signature().return_type != TypeOracle::GetNeverType()) {
169  Stack<const Type*> return_stack = *stack;
170  return_stack.PushMany(LowerType(macro->signature().return_type));
171  if (return_continuation == base::nullopt) {
172  ReportError("missing return continuation.");
173  }
174  (*return_continuation)->SetInputTypes(return_stack);
175  } else {
176  if (return_continuation != base::nullopt) {
177  ReportError("unreachable return continuation.");
178  }
179  }
180 }
181 
182 void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
183  ControlFlowGraph* cfg) const {
184  std::vector<const Type*> argument_types = stack->PopMany(argc);
185  if (argument_types !=
186  LowerParameterTypes(builtin->signature().parameter_types)) {
187  ReportError("wrong argument types");
188  }
189  if (builtin->IsTransitioning()) {
190  InvalidateTransientTypes(stack);
191  }
192 
193  if (catch_block) {
194  Stack<const Type*> catch_stack = *stack;
195  catch_stack.Push(TypeOracle::GetObjectType());
196  (*catch_block)->SetInputTypes(catch_stack);
197  }
198 
199  stack->PushMany(LowerType(builtin->signature().return_type));
200 }
201 
202 void CallBuiltinPointerInstruction::TypeInstruction(
203  Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
204  std::vector<const Type*> argument_types = stack->PopMany(argc);
205  const FunctionPointerType* f = FunctionPointerType::DynamicCast(stack->Pop());
206  if (!f) ReportError("expected function pointer type");
207  if (argument_types != LowerParameterTypes(f->parameter_types())) {
208  ReportError("wrong argument types");
209  }
210  // TODO(tebbi): Only invalidate transient types if the function pointer type
211  // is transitioning.
212  InvalidateTransientTypes(stack);
213  stack->PushMany(LowerType(f->return_type()));
214 }
215 
216 void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
217  ControlFlowGraph* cfg) const {
218  std::vector<const Type*> argument_types = stack->PopMany(argc);
219  if (argument_types !=
220  LowerParameterTypes(runtime_function->signature().parameter_types,
221  argc)) {
222  ReportError("wrong argument types");
223  }
224  if (runtime_function->IsTransitioning()) {
225  InvalidateTransientTypes(stack);
226  }
227 
228  if (catch_block) {
229  Stack<const Type*> catch_stack = *stack;
230  catch_stack.Push(TypeOracle::GetObjectType());
231  (*catch_block)->SetInputTypes(catch_stack);
232  }
233 
234  const Type* return_type = runtime_function->signature().return_type;
235  if (return_type != TypeOracle::GetNeverType()) {
236  stack->PushMany(LowerType(return_type));
237  }
238 }
239 
240 void BranchInstruction::TypeInstruction(Stack<const Type*>* stack,
241  ControlFlowGraph* cfg) const {
242  const Type* condition_type = stack->Pop();
243  if (condition_type != TypeOracle::GetBoolType()) {
244  ReportError("condition has to have type bool");
245  }
246  if_true->SetInputTypes(*stack);
247  if_false->SetInputTypes(*stack);
248 }
249 
250 void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack,
251  ControlFlowGraph* cfg) const {
252  if_true->SetInputTypes(*stack);
253  if_false->SetInputTypes(*stack);
254 }
255 
256 void GotoInstruction::TypeInstruction(Stack<const Type*>* stack,
257  ControlFlowGraph* cfg) const {
258  destination->SetInputTypes(*stack);
259 }
260 
261 void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack,
262  ControlFlowGraph* cfg) const {
263  if (variable_names.size() != stack->Size()) {
264  ReportError("goto external label with wrong parameter count.");
265  }
266 }
267 
268 void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
269  ControlFlowGraph* cfg) const {
270  cfg->SetReturnType(stack->Pop());
271 }
272 
273 void PrintConstantStringInstruction::TypeInstruction(
274  Stack<const Type*>* stack, ControlFlowGraph* cfg) const {}
275 
276 void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
277  ControlFlowGraph* cfg) const {}
278 
279 void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
280  ControlFlowGraph* cfg) const {
281  stack->Poke(stack->AboveTop() - 1, destination_type);
282 }
283 
284 bool CallRuntimeInstruction::IsBlockTerminator() const {
285  return is_tailcall || runtime_function->signature().return_type ==
286  TypeOracle::GetNeverType();
287 }
288 
289 } // namespace torque
290 } // namespace internal
291 } // namespace v8
Definition: libplatform.h:13