Chromium Code Reviews

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

Powered by Google App Engine