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

Side by Side Diff: src/compiler/typer.cc

Issue 509343002: Better typing and type verification (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Small refactoring Created 6 years, 2 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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/bootstrapper.h"
5 #include "src/compiler/graph-inl.h" 6 #include "src/compiler/graph-inl.h"
6 #include "src/compiler/js-operator.h" 7 #include "src/compiler/js-operator.h"
7 #include "src/compiler/node.h" 8 #include "src/compiler/node.h"
8 #include "src/compiler/node-properties-inl.h" 9 #include "src/compiler/node-properties-inl.h"
9 #include "src/compiler/node-properties.h" 10 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h" 11 #include "src/compiler/simplified-operator.h"
11 #include "src/compiler/typer.h" 12 #include "src/compiler/typer.h"
12 13
13 namespace v8 { 14 namespace v8 {
14 namespace internal { 15 namespace internal {
15 namespace compiler { 16 namespace compiler {
16 17
17 Typer::Typer(Zone* zone) : zone_(zone) { 18
19 class Typer::Decorator : public GraphDecorator {
20 public:
21 explicit Decorator(Typer* typer) : typer_(typer) {}
22 virtual void Decorate(Node* node);
23
24 private:
25 static bool AllInputsAreTyped(Node* node);
26 Typer* typer_;
27 };
28
29
30 Typer::Typer(Graph* graph, MaybeHandle<Context> context)
31 : graph_(graph), context_(context), decorator_(NULL) {
32 Zone* zone = this->zone();
18 Type* number = Type::Number(zone); 33 Type* number = Type::Number(zone);
19 Type* signed32 = Type::Signed32(zone); 34 Type* signed32 = Type::Signed32(zone);
20 Type* unsigned32 = Type::Unsigned32(zone); 35 Type* unsigned32 = Type::Unsigned32(zone);
21 Type* integral32 = Type::Integral32(zone); 36 Type* integral32 = Type::Integral32(zone);
22 Type* object = Type::Object(zone); 37 Type* object = Type::Object(zone);
23 Type* undefined = Type::Undefined(zone); 38 Type* undefined = Type::Undefined(zone);
24 number_fun0_ = Type::Function(number, zone); 39 number_fun0_ = Type::Function(number, zone);
25 number_fun1_ = Type::Function(number, number, zone); 40 number_fun1_ = Type::Function(number, number, zone);
26 number_fun2_ = Type::Function(number, number, number, zone); 41 number_fun2_ = Type::Function(number, number, number, zone);
27 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); 42 imul_fun_ = Type::Function(signed32, integral32, integral32, zone);
(...skipping 24 matching lines...) Expand all
52 Type* arg3 = arg2; 67 Type* arg3 = arg2;
53 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); 68 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone);
54 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); 69 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone);
55 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); 70 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone);
56 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); 71 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone);
57 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); 72 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone);
58 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); 73 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone);
59 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); 74 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone);
60 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); 75 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone);
61 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); 76 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone);
77
78 decorator_ = new (zone) Decorator(this);
79 graph_->AddDecorator(decorator_);
80 }
81
82
83 Typer::~Typer() {
84 if (decorator_) graph_->RemoveDecorator(decorator_);
62 } 85 }
63 86
64 87
65 class Typer::Visitor : public NullNodeVisitor { 88 class Typer::Visitor : public NullNodeVisitor {
66 public: 89 public:
67 Visitor(Typer* typer, MaybeHandle<Context> context) 90 explicit Visitor(Typer* typer) : typer_(typer) {}
68 : typer_(typer), context_(context) {}
69 91
70 Bounds TypeNode(Node* node) { 92 Bounds TypeNode(Node* node) {
71 switch (node->opcode()) { 93 switch (node->opcode()) {
72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); 94 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
95 DECLARE_CASE(Start)
73 VALUE_OP_LIST(DECLARE_CASE) 96 VALUE_OP_LIST(DECLARE_CASE)
74 #undef DECLARE_CASE 97 #undef DECLARE_CASE
75 98
76 #define DECLARE_CASE(x) case IrOpcode::k##x: 99 #define DECLARE_CASE(x) case IrOpcode::k##x:
77 CONTROL_OP_LIST(DECLARE_CASE) 100 DECLARE_CASE(End)
101 INNER_CONTROL_OP_LIST(DECLARE_CASE)
78 #undef DECLARE_CASE 102 #undef DECLARE_CASE
79 break; 103 break;
80 } 104 }
81 return Bounds(Type::None(zone())); 105 UNREACHABLE();
106 return Bounds();
82 } 107 }
83 108
84 Type* TypeConstant(Handle<Object> value); 109 Type* TypeConstant(Handle<Object> value);
85 110
86 protected: 111 protected:
87 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); 112 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
113 DECLARE_METHOD(Start)
88 VALUE_OP_LIST(DECLARE_METHOD) 114 VALUE_OP_LIST(DECLARE_METHOD)
89 #undef DECLARE_METHOD 115 #undef DECLARE_METHOD
90 116
91 Bounds OperandType(Node* node, int i) { 117 Bounds operand(Node* node, int i) {
92 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); 118 Node* operand_node = NodeProperties::GetValueInput(node, i);
119 return GetBoundsOrNone(operand_node);
93 } 120 }
94 121
95 Type* ContextType(Node* node) { 122 Type* context_type(Node* node) {
96 Bounds result = 123 Bounds result = GetBoundsOrNone(NodeProperties::GetContextInput(node));
97 NodeProperties::GetBounds(NodeProperties::GetContextInput(node)); 124 DCHECK(result.upper->Maybe(Type::Internal()));
98 DCHECK(result.upper->Is(Type::Internal()));
99 DCHECK(result.lower->Equals(result.upper));
100 return result.upper; 125 return result.upper;
101 } 126 }
102 127
103 Zone* zone() { return typer_->zone(); } 128 Zone* zone() { return typer_->zone(); }
104 Isolate* isolate() { return typer_->isolate(); } 129 Isolate* isolate() { return typer_->isolate(); }
105 MaybeHandle<Context> context() { return context_; } 130 Graph* graph() { return typer_->graph(); }
131 MaybeHandle<Context> context() { return typer_->context(); }
106 132
107 private: 133 private:
108 Typer* typer_; 134 Typer* typer_;
109 MaybeHandle<Context> context_; 135
136 Bounds GetBoundsOrNone(Node* node) {
137 return NodeProperties::IsTyped(node)
138 ? NodeProperties::GetBounds(node) : Bounds(Type::None(zone()));
139 }
110 }; 140 };
111 141
112 142
113 class Typer::RunVisitor : public Typer::Visitor { 143 class Typer::RunVisitor : public Typer::Visitor {
114 public: 144 public:
115 RunVisitor(Typer* typer, MaybeHandle<Context> context) 145 explicit RunVisitor(Typer* typer)
116 : Visitor(typer, context), 146 : Visitor(typer),
117 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} 147 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {}
118 148
119 GenericGraphVisit::Control Pre(Node* node) {
120 return NodeProperties::IsControl(node)
121 && node->opcode() != IrOpcode::kEnd
122 && node->opcode() != IrOpcode::kMerge
123 && node->opcode() != IrOpcode::kReturn
124 ? GenericGraphVisit::SKIP : GenericGraphVisit::CONTINUE;
125 }
126
127 GenericGraphVisit::Control Post(Node* node) { 149 GenericGraphVisit::Control Post(Node* node) {
128 Bounds bounds = TypeNode(node); 150 if (OperatorProperties::HasValueOutput(node->op())) {
129 if (node->opcode() == IrOpcode::kPhi) { 151 Bounds bounds = TypeNode(node);
152 NodeProperties::SetBounds(node, bounds);
130 // Remember phis for least fixpoint iteration. 153 // Remember phis for least fixpoint iteration.
131 phis.insert(node); 154 if (node->opcode() == IrOpcode::kPhi) phis.insert(node);
132 } else {
133 NodeProperties::SetBounds(node, bounds);
134 } 155 }
135 return GenericGraphVisit::CONTINUE; 156 return GenericGraphVisit::CONTINUE;
136 } 157 }
137 158
138 NodeSet phis; 159 NodeSet phis;
139 }; 160 };
140 161
141 162
142 class Typer::NarrowVisitor : public Typer::Visitor { 163 class Typer::NarrowVisitor : public Typer::Visitor {
143 public: 164 public:
144 NarrowVisitor(Typer* typer, MaybeHandle<Context> context) 165 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {}
145 : Visitor(typer, context) {}
146 166
147 GenericGraphVisit::Control Pre(Node* node) { 167 GenericGraphVisit::Control Pre(Node* node) {
148 Bounds previous = NodeProperties::GetBounds(node); 168 if (OperatorProperties::HasValueOutput(node->op())) {
149 Bounds bounds = TypeNode(node); 169 Bounds previous = NodeProperties::GetBounds(node);
150 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); 170 Bounds bounds = TypeNode(node);
151 DCHECK(bounds.Narrows(previous)); 171 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone()));
152 // Stop when nothing changed (but allow reentry in case it does later). 172 DCHECK(bounds.Narrows(previous));
153 return previous.Narrows(bounds) 173 // Stop when nothing changed (but allow re-entry in case it does later).
154 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 174 return previous.Narrows(bounds)
175 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
176 } else {
177 return GenericGraphVisit::SKIP;
178 }
155 } 179 }
156 180
157 GenericGraphVisit::Control Post(Node* node) { 181 GenericGraphVisit::Control Post(Node* node) {
158 return GenericGraphVisit::REENTER; 182 return GenericGraphVisit::REENTER;
159 } 183 }
160 }; 184 };
161 185
162 186
163 class Typer::WidenVisitor : public Typer::Visitor { 187 class Typer::WidenVisitor : public Typer::Visitor {
164 public: 188 public:
165 WidenVisitor(Typer* typer, MaybeHandle<Context> context) 189 explicit WidenVisitor(Typer* typer) : Visitor(typer) {}
166 : Visitor(typer, context) {}
167 190
168 GenericGraphVisit::Control Pre(Node* node) { 191 GenericGraphVisit::Control Pre(Node* node) {
169 Bounds previous = NodeProperties::GetBounds(node); 192 if (OperatorProperties::HasValueOutput(node->op())) {
170 Bounds bounds = TypeNode(node); 193 Bounds previous = NodeProperties::GetBounds(node);
171 DCHECK(previous.lower->Is(bounds.lower)); 194 Bounds bounds = TypeNode(node);
172 DCHECK(previous.upper->Is(bounds.upper)); 195 DCHECK(previous.lower->Is(bounds.lower));
173 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either? 196 DCHECK(previous.upper->Is(bounds.upper));
174 // Stop when nothing changed (but allow reentry in case it does later). 197 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either?
175 return bounds.Narrows(previous) 198 // Stop when nothing changed (but allow re-entry in case it does later).
176 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 199 return bounds.Narrows(previous)
200 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
201 } else {
202 return GenericGraphVisit::SKIP;
203 }
177 } 204 }
178 205
179 GenericGraphVisit::Control Post(Node* node) { 206 GenericGraphVisit::Control Post(Node* node) {
180 return GenericGraphVisit::REENTER; 207 return GenericGraphVisit::REENTER;
181 } 208 }
182 }; 209 };
183 210
184 211
185 void Typer::Run(Graph* graph, MaybeHandle<Context> context) { 212 void Typer::Run() {
186 RunVisitor typing(this, context); 213 RunVisitor typing(this);
187 graph->VisitNodeInputsFromEnd(&typing); 214 graph_->VisitNodeInputsFromEnd(&typing);
188 // Find least fixpoint. 215 // Find least fixpoint.
189 for (NodeSetIter i = typing.phis.begin(); i != typing.phis.end(); ++i) { 216 WidenVisitor widen(this);
190 Widen(graph, *i, context); 217 for (NodeSetIter it = typing.phis.begin(); it != typing.phis.end(); ++it) {
218 graph_->VisitNodeUsesFrom(*it, &widen);
191 } 219 }
192 } 220 }
193 221
194 222
195 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) { 223 void Typer::Narrow(Node* start) {
196 NarrowVisitor typing(this, context); 224 NarrowVisitor typing(this);
197 graph->VisitNodeUsesFrom(start, &typing); 225 graph_->VisitNodeUsesFrom(start, &typing);
198 } 226 }
199 227
200 228
201 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) { 229 void Typer::Decorator::Decorate(Node* node) {
202 WidenVisitor typing(this, context); 230 if (OperatorProperties::HasValueOutput(node->op())) {
203 graph->VisitNodeUsesFrom(start, &typing); 231 // Only eagerly type-decorate nodes with known input types.
232 // Other cases will generally require a proper fixpoint iteration with Run.
233 bool is_typed = NodeProperties::IsTyped(node);
234 if (is_typed || AllInputsAreTyped(node)) {
235 Visitor typing(typer_);
236 Bounds bounds = typing.TypeNode(node);
237 if (is_typed) {
238 bounds =
239 Bounds::Both(bounds, NodeProperties::GetBounds(node), typer_->zone());
240 }
241 NodeProperties::SetBounds(node, bounds);
242 }
243 }
204 } 244 }
205 245
206 246
207 void Typer::Init(Node* node) { 247 bool Typer::Decorator::AllInputsAreTyped(Node* node) {
208 Visitor typing(this, MaybeHandle<Context>()); 248 int input_count = OperatorProperties::GetValueInputCount(node->op());
209 Bounds bounds = typing.TypeNode(node); 249 for (int i = 0; i < input_count; ++i) {
210 NodeProperties::SetBounds(node, bounds); 250 if (!NodeProperties::IsTyped(NodeProperties::GetValueInput(node, i))) {
251 return false;
252 }
253 }
254 return OperatorProperties::GetContextInputCount(node->op()) == 0
255 || NodeProperties::IsTyped(NodeProperties::GetContextInput(node));
256 }
257
258
259 // -----------------------------------------------------------------------------
260 // Control operators.
261
262 Bounds Typer::Visitor::TypeStart(Node* node) {
263 return Bounds(Type::Internal(zone()));
211 } 264 }
212 265
213 266
214 // Common operators. 267 // Common operators.
268
215 Bounds Typer::Visitor::TypeParameter(Node* node) { 269 Bounds Typer::Visitor::TypeParameter(Node* node) {
216 return Bounds::Unbounded(zone()); 270 return Bounds::Unbounded(zone());
217 } 271 }
218 272
219 273
220 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { 274 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
221 // TODO(titzer): only call Type::Of() if the type is not already known. 275 // TODO(titzer): only call Type::Of() if the type is not already known.
222 return Bounds(Type::Of(ValueOf<int32_t>(node->op()), zone())); 276 return Bounds(Type::Of(ValueOf<int32_t>(node->op()), zone()));
223 } 277 }
224 278
(...skipping 22 matching lines...) Expand all
247 } 301 }
248 302
249 303
250 Bounds Typer::Visitor::TypeExternalConstant(Node* node) { 304 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
251 return Bounds(Type::Internal(zone())); 305 return Bounds(Type::Internal(zone()));
252 } 306 }
253 307
254 308
255 Bounds Typer::Visitor::TypePhi(Node* node) { 309 Bounds Typer::Visitor::TypePhi(Node* node) {
256 int arity = OperatorProperties::GetValueInputCount(node->op()); 310 int arity = OperatorProperties::GetValueInputCount(node->op());
257 Bounds bounds = OperandType(node, 0); 311 Bounds bounds = operand(node, 0);
258 for (int i = 1; i < arity; ++i) { 312 for (int i = 1; i < arity; ++i) {
259 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); 313 bounds = Bounds::Either(bounds, operand(node, i), zone());
260 } 314 }
261 return bounds; 315 return bounds;
262 } 316 }
263 317
264 318
265 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { 319 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
266 return Bounds(Type::None(zone())); 320 UNREACHABLE();
321 return Bounds();
267 } 322 }
268 323
269 324
270 Bounds Typer::Visitor::TypeControlEffect(Node* node) { 325 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
271 return Bounds(Type::None(zone())); 326 UNREACHABLE();
327 return Bounds();
272 } 328 }
273 329
274 330
275 Bounds Typer::Visitor::TypeValueEffect(Node* node) { 331 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
276 return Bounds(Type::None(zone())); 332 UNREACHABLE();
333 return Bounds();
277 } 334 }
278 335
279 336
280 Bounds Typer::Visitor::TypeFinish(Node* node) { return OperandType(node, 0); } 337 Bounds Typer::Visitor::TypeFinish(Node* node) {
338 return operand(node, 0);
339 }
281 340
282 341
283 Bounds Typer::Visitor::TypeFrameState(Node* node) { 342 Bounds Typer::Visitor::TypeFrameState(Node* node) {
284 return Bounds(Type::None(zone())); 343 return Bounds::Unbounded(zone());
285 } 344 }
286 345
287 346
288 Bounds Typer::Visitor::TypeStateValues(Node* node) { 347 Bounds Typer::Visitor::TypeStateValues(Node* node) {
289 return Bounds(Type::None(zone())); 348 return Bounds::Unbounded(zone());
290 } 349 }
291 350
292 351
293 Bounds Typer::Visitor::TypeCall(Node* node) { 352 Bounds Typer::Visitor::TypeCall(Node* node) {
294 return Bounds::Unbounded(zone()); 353 return Bounds::Unbounded(zone());
295 } 354 }
296 355
297 356
298 Bounds Typer::Visitor::TypeProjection(Node* node) { 357 Bounds Typer::Visitor::TypeProjection(Node* node) {
299 // TODO(titzer): use the output type of the input to determine the bounds. 358 // TODO(titzer): use the output type of the input to determine the bounds.
300 return Bounds::Unbounded(zone()); 359 return Bounds::Unbounded(zone());
301 } 360 }
302 361
303 362
304 // JS comparison operators. 363 // JS comparison operators.
305 364
306 #define DEFINE_METHOD(x) \ 365 #define DEFINE_METHOD(x) \
307 Bounds Typer::Visitor::Type##x(Node* node) { \ 366 Bounds Typer::Visitor::Type##x(Node* node) { \
308 return Bounds(Type::Boolean(zone())); \ 367 return Bounds(Type::Boolean(zone())); \
309 } 368 }
310 JS_COMPARE_BINOP_LIST(DEFINE_METHOD) 369 JS_COMPARE_BINOP_LIST(DEFINE_METHOD)
311 #undef DEFINE_METHOD 370 #undef DEFINE_METHOD
312 371
313 372
314 // JS bitwise operators. 373 // JS bitwise operators.
315 374
316 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) { 375 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) {
317 Bounds left = OperandType(node, 0); 376 Bounds left = operand(node, 0);
318 Bounds right = OperandType(node, 1); 377 Bounds right = operand(node, 1);
319 Type* upper = Type::Union(left.upper, right.upper, zone()); 378 Type* upper = Type::Union(left.upper, right.upper, zone());
320 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 379 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
321 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 380 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
322 return Bounds(lower, upper); 381 return Bounds(lower, upper);
323 } 382 }
324 383
325 384
326 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) { 385 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) {
327 Bounds left = OperandType(node, 0); 386 Bounds left = operand(node, 0);
328 Bounds right = OperandType(node, 1); 387 Bounds right = operand(node, 1);
329 Type* upper = Type::Union(left.upper, right.upper, zone()); 388 Type* upper = Type::Union(left.upper, right.upper, zone());
330 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); 389 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone());
331 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); 390 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone());
332 return Bounds(lower, upper); 391 return Bounds(lower, upper);
333 } 392 }
334 393
335 394
336 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) { 395 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
337 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); 396 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone()));
338 } 397 }
(...skipping 10 matching lines...) Expand all
349 408
350 409
351 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) { 410 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
352 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone())); 411 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone()));
353 } 412 }
354 413
355 414
356 // JS arithmetic operators. 415 // JS arithmetic operators.
357 416
358 Bounds Typer::Visitor::TypeJSAdd(Node* node) { 417 Bounds Typer::Visitor::TypeJSAdd(Node* node) {
359 Bounds left = OperandType(node, 0); 418 Bounds left = operand(node, 0);
360 Bounds right = OperandType(node, 1); 419 Bounds right = operand(node, 1);
361 Type* lower = 420 Type* lower =
362 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ? 421 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ?
363 Type::None(zone()) : 422 Type::None(zone()) :
364 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ? 423 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ?
365 Type::SignedSmall(zone()) : 424 Type::SignedSmall(zone()) :
366 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ? 425 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ?
367 Type::String(zone()) : Type::None(zone()); 426 Type::String(zone()) : Type::None(zone());
368 Type* upper = 427 Type* upper =
369 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ? 428 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ?
370 Type::None(zone()) : 429 Type::None(zone()) :
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 return Bounds(Type::None(zone()), Type::String(zone())); 483 return Bounds(Type::None(zone()), Type::String(zone()));
425 } 484 }
426 485
427 486
428 Bounds Typer::Visitor::TypeJSToName(Node* node) { 487 Bounds Typer::Visitor::TypeJSToName(Node* node) {
429 return Bounds(Type::None(zone()), Type::Name(zone())); 488 return Bounds(Type::None(zone()), Type::Name(zone()));
430 } 489 }
431 490
432 491
433 Bounds Typer::Visitor::TypeJSToObject(Node* node) { 492 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
434 return Bounds(Type::None(zone()), Type::Object(zone())); 493 return Bounds(Type::None(zone()), Type::Receiver(zone()));
435 } 494 }
436 495
437 496
438 // JS object operators. 497 // JS object operators.
439 498
440 Bounds Typer::Visitor::TypeJSCreate(Node* node) { 499 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
441 return Bounds(Type::None(zone()), Type::Object(zone())); 500 return Bounds(Type::None(zone()), Type::Object(zone()));
442 } 501 }
443 502
444 503
445 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { 504 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
446 Bounds object = OperandType(node, 0); 505 Bounds object = operand(node, 0);
447 Bounds name = OperandType(node, 1); 506 Bounds name = operand(node, 1);
448 Bounds result = Bounds::Unbounded(zone()); 507 Bounds result = Bounds::Unbounded(zone());
449 // TODO(rossberg): Use range types and sized array types to filter undefined. 508 // TODO(rossberg): Use range types and sized array types to filter undefined.
450 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) { 509 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) {
451 result.lower = Type::Union( 510 result.lower = Type::Union(
452 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone()); 511 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone());
453 } 512 }
454 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) { 513 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) {
455 result.upper = Type::Union( 514 result.upper = Type::Union(
456 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone()); 515 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone());
457 } 516 }
458 return result; 517 return result;
459 } 518 }
460 519
461 520
462 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { 521 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
463 return Bounds::Unbounded(zone()); 522 return Bounds::Unbounded(zone());
464 } 523 }
465 524
466 525
467 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { 526 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
468 return Bounds(Type::None(zone())); 527 UNREACHABLE();
528 return Bounds();
469 } 529 }
470 530
471 531
472 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { 532 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
473 return Bounds(Type::None(zone())); 533 UNREACHABLE();
534 return Bounds();
474 } 535 }
475 536
476 537
477 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { 538 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
478 return Bounds(Type::Boolean(zone())); 539 return Bounds(Type::Boolean(zone()));
479 } 540 }
480 541
481 542
482 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { 543 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
483 return Bounds(Type::Boolean(zone())); 544 return Bounds(Type::Boolean(zone()));
484 } 545 }
485 546
486 547
487 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) { 548 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
488 return Bounds(Type::Boolean(zone())); 549 return Bounds(Type::Boolean(zone()));
489 } 550 }
490 551
491 552
492 // JS context operators. 553 // JS context operators.
493 554
494 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { 555 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
495 Bounds outer = OperandType(node, 0); 556 Bounds outer = operand(node, 0);
496 DCHECK(outer.upper->Is(Type::Internal())); 557 DCHECK(outer.upper->Maybe(Type::Internal()));
497 DCHECK(outer.lower->Equals(outer.upper)); 558 // TODO(rossberg): More precisely, instead of the above assertion, we should
559 // back-propagate the constraint that it has to be a subtype of Internal.
560
498 ContextAccess access = OpParameter<ContextAccess>(node); 561 ContextAccess access = OpParameter<ContextAccess>(node);
499 Type* context_type = outer.upper; 562 Type* context_type = outer.upper;
500 MaybeHandle<Context> context; 563 MaybeHandle<Context> context;
501 if (context_type->IsConstant()) { 564 if (context_type->IsConstant()) {
502 context = Handle<Context>::cast(context_type->AsConstant()->Value()); 565 context = Handle<Context>::cast(context_type->AsConstant()->Value());
503 } 566 }
504 // Walk context chain (as far as known), mirroring dynamic lookup. 567 // Walk context chain (as far as known), mirroring dynamic lookup.
505 // Since contexts are mutable, the information is only useful as a lower 568 // Since contexts are mutable, the information is only useful as a lower
506 // bound. 569 // bound.
507 // TODO(rossberg): Could use scope info to fix upper bounds for constant 570 // TODO(rossberg): Could use scope info to fix upper bounds for constant
508 // bindings if we know that this code is never shared. 571 // bindings if we know that this code is never shared.
509 for (int i = access.depth(); i > 0; --i) { 572 for (int i = access.depth(); i > 0; --i) {
510 if (context_type->IsContext()) { 573 if (context_type->IsContext()) {
511 context_type = context_type->AsContext()->Outer(); 574 context_type = context_type->AsContext()->Outer();
512 if (context_type->IsConstant()) { 575 if (context_type->IsConstant()) {
513 context = Handle<Context>::cast(context_type->AsConstant()->Value()); 576 context = Handle<Context>::cast(context_type->AsConstant()->Value());
514 } 577 }
515 } else { 578 } else if (!context.is_null()) {
516 context = handle(context.ToHandleChecked()->previous(), isolate()); 579 context = handle(context.ToHandleChecked()->previous(), isolate());
517 } 580 }
518 } 581 }
519 if (context.is_null()) { 582 if (context.is_null()) {
520 return Bounds::Unbounded(zone()); 583 return Bounds::Unbounded(zone());
521 } else { 584 } else {
522 Handle<Object> value = 585 Handle<Object> value =
523 handle(context.ToHandleChecked()->get(access.index()), isolate()); 586 handle(context.ToHandleChecked()->get(access.index()), isolate());
524 Type* lower = TypeConstant(value); 587 Type* lower = TypeConstant(value);
525 return Bounds(lower, Type::Any(zone())); 588 return Bounds(lower, Type::Any(zone()));
526 } 589 }
527 } 590 }
528 591
529 592
530 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { 593 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
531 return Bounds(Type::None(zone())); 594 UNREACHABLE();
595 return Bounds();
532 } 596 }
533 597
534 598
535 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { 599 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
536 Type* outer = ContextType(node); 600 Type* outer = context_type(node);
537 return Bounds(Type::Context(outer, zone())); 601 return Bounds(Type::Context(outer, zone()));
538 } 602 }
539 603
540 604
541 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { 605 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
542 Type* outer = ContextType(node); 606 Type* outer = context_type(node);
543 return Bounds(Type::Context(outer, zone())); 607 return Bounds(Type::Context(outer, zone()));
544 } 608 }
545 609
546 610
547 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) { 611 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
548 Type* outer = ContextType(node); 612 Type* outer = context_type(node);
549 return Bounds(Type::Context(outer, zone())); 613 return Bounds(Type::Context(outer, zone()));
550 } 614 }
551 615
552 616
553 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) { 617 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
554 Type* outer = ContextType(node); 618 Type* outer = context_type(node);
555 return Bounds(Type::Context(outer, zone())); 619 return Bounds(Type::Context(outer, zone()));
556 } 620 }
557 621
558 622
559 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) { 623 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
560 // TODO(rossberg): this is probably incorrect 624 // TODO(rossberg): this is probably incorrect
561 Type* outer = ContextType(node); 625 Type* outer = context_type(node);
562 return Bounds(Type::Context(outer, zone())); 626 return Bounds(Type::Context(outer, zone()));
563 } 627 }
564 628
565 629
566 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) { 630 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
567 Type* outer = ContextType(node); 631 Type* outer = context_type(node);
568 return Bounds(Type::Context(outer, zone())); 632 return Bounds(Type::Context(outer, zone()));
569 } 633 }
570 634
571 635
572 // JS other operators. 636 // JS other operators.
573 637
574 Bounds Typer::Visitor::TypeJSYield(Node* node) { 638 Bounds Typer::Visitor::TypeJSYield(Node* node) {
575 return Bounds::Unbounded(zone()); 639 return Bounds::Unbounded(zone());
576 } 640 }
577 641
578 642
579 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) { 643 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
580 return Bounds(Type::None(zone()), Type::Receiver(zone())); 644 return Bounds(Type::None(zone()), Type::Receiver(zone()));
581 } 645 }
582 646
583 647
584 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) { 648 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
585 Bounds fun = OperandType(node, 0); 649 Bounds fun = operand(node, 0);
586 Type* lower = fun.lower->IsFunction() 650 Type* lower = fun.lower->IsFunction()
587 ? fun.lower->AsFunction()->Result() : Type::None(zone()); 651 ? fun.lower->AsFunction()->Result() : Type::None(zone());
588 Type* upper = fun.upper->IsFunction() 652 Type* upper = fun.upper->IsFunction()
589 ? fun.upper->AsFunction()->Result() : Type::Any(zone()); 653 ? fun.upper->AsFunction()->Result() : Type::Any(zone());
590 return Bounds(lower, upper); 654 return Bounds(lower, upper);
591 } 655 }
592 656
593 657
594 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { 658 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
595 return Bounds::Unbounded(zone()); 659 return Bounds::Unbounded(zone());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 return Bounds(Type::Number(zone())); 706 return Bounds(Type::Number(zone()));
643 } 707 }
644 708
645 709
646 Bounds Typer::Visitor::TypeNumberModulus(Node* node) { 710 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
647 return Bounds(Type::Number(zone())); 711 return Bounds(Type::Number(zone()));
648 } 712 }
649 713
650 714
651 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) { 715 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
652 Bounds arg = OperandType(node, 0); 716 Bounds arg = operand(node, 0);
653 Type* s32 = Type::Signed32(zone()); 717 Type* s32 = Type::Signed32(zone());
654 Type* lower = arg.lower->Is(s32) ? arg.lower : s32; 718 Type* lower = arg.lower->Is(s32) ? arg.lower : s32;
655 Type* upper = arg.upper->Is(s32) ? arg.upper : s32; 719 Type* upper = arg.upper->Is(s32) ? arg.upper : s32;
656 return Bounds(lower, upper); 720 return Bounds(lower, upper);
657 } 721 }
658 722
659 723
660 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) { 724 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
661 Bounds arg = OperandType(node, 0); 725 Bounds arg = operand(node, 0);
662 Type* u32 = Type::Unsigned32(zone()); 726 Type* u32 = Type::Unsigned32(zone());
663 Type* lower = arg.lower->Is(u32) ? arg.lower : u32; 727 Type* lower = arg.lower->Is(u32) ? arg.lower : u32;
664 Type* upper = arg.upper->Is(u32) ? arg.upper : u32; 728 Type* upper = arg.upper->Is(u32) ? arg.upper : u32;
665 return Bounds(lower, upper); 729 return Bounds(lower, upper);
666 } 730 }
667 731
668 732
669 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) { 733 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
670 return Bounds(Type::Boolean(zone())); 734 return Bounds(Type::Boolean(zone()));
671 } 735 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 return Bounds(FieldAccessOf(node->op()).type); 806 return Bounds(FieldAccessOf(node->op()).type);
743 } 807 }
744 808
745 809
746 Bounds Typer::Visitor::TypeLoadElement(Node* node) { 810 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
747 return Bounds(ElementAccessOf(node->op()).type); 811 return Bounds(ElementAccessOf(node->op()).type);
748 } 812 }
749 813
750 814
751 Bounds Typer::Visitor::TypeStoreField(Node* node) { 815 Bounds Typer::Visitor::TypeStoreField(Node* node) {
752 return Bounds(Type::None()); 816 UNREACHABLE();
817 return Bounds();
753 } 818 }
754 819
755 820
756 Bounds Typer::Visitor::TypeStoreElement(Node* node) { 821 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
757 return Bounds(Type::None()); 822 UNREACHABLE();
823 return Bounds();
758 } 824 }
759 825
760 826
761 // Machine operators. 827 // Machine operators.
762 828
763 // TODO(rossberg): implement 829 // TODO(rossberg): implement
764 #define DEFINE_METHOD(x) \ 830 #define DEFINE_METHOD(x) \
765 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); } 831 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); }
766 MACHINE_OP_LIST(DEFINE_METHOD) 832 MACHINE_OP_LIST(DEFINE_METHOD)
767 #undef DEFINE_METHOD 833 #undef DEFINE_METHOD
768 834
769 835
770 // Heap constants. 836 // Heap constants.
771 837
772 Type* Typer::Visitor::TypeConstant(Handle<Object> value) { 838 Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
773 if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() && 839 if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() &&
774 !context().is_null()) { 840 !context().is_null() && !isolate()->bootstrapper()->IsActive()) {
775 Handle<Context> native = 841 Handle<Context> native =
776 handle(context().ToHandleChecked()->native_context(), isolate()); 842 handle(context().ToHandleChecked()->native_context(), isolate());
777 if (*value == native->math_abs_fun()) { 843 if (*value == native->math_abs_fun()) {
778 return typer_->number_fun1_; // TODO(rossberg): can't express overloading 844 return typer_->number_fun1_; // TODO(rossberg): can't express overloading
779 } else if (*value == native->math_acos_fun()) { 845 } else if (*value == native->math_acos_fun()) {
780 return typer_->number_fun1_; 846 return typer_->number_fun1_;
781 } else if (*value == native->math_asin_fun()) { 847 } else if (*value == native->math_asin_fun()) {
782 return typer_->number_fun1_; 848 return typer_->number_fun1_;
783 } else if (*value == native->math_atan_fun()) { 849 } else if (*value == native->math_atan_fun()) {
784 return typer_->number_fun1_; 850 return typer_->number_fun1_;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 return typer_->uint32_array_fun_; 890 return typer_->uint32_array_fun_;
825 } else if (*value == native->float32_array_fun()) { 891 } else if (*value == native->float32_array_fun()) {
826 return typer_->float32_array_fun_; 892 return typer_->float32_array_fun_;
827 } else if (*value == native->float64_array_fun()) { 893 } else if (*value == native->float64_array_fun()) {
828 return typer_->float64_array_fun_; 894 return typer_->float64_array_fun_;
829 } 895 }
830 } 896 }
831 return Type::Constant(value, zone()); 897 return Type::Constant(value, zone());
832 } 898 }
833 899
834
835 namespace {
836
837 class TyperDecorator : public GraphDecorator {
838 public:
839 explicit TyperDecorator(Typer* typer) : typer_(typer) {}
840 virtual void Decorate(Node* node) { typer_->Init(node); }
841
842 private:
843 Typer* typer_;
844 };
845
846 }
847
848
849 void Typer::DecorateGraph(Graph* graph) {
850 graph->AddDecorator(new (zone()) TyperDecorator(this));
851 }
852
853 } 900 }
854 } 901 }
855 } // namespace v8::internal::compiler 902 } // namespace v8::internal::compiler
OLDNEW
« src/compiler/typer.h ('K') | « src/compiler/typer.h ('k') | src/compiler/verifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698