| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |