• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "src/code-factory.h"
6 #include "src/compilation-dependencies.h"
7 #include "src/compiler/access-builder.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-typed-lowering.h"
10 #include "src/compiler/linkage.h"
11 #include "src/compiler/node-matchers.h"
12 #include "src/compiler/node-properties.h"
13 #include "src/compiler/operator-properties.h"
14 #include "src/type-cache.h"
15 #include "src/types.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace compiler {
20 
21 // A helper class to simplify the process of reducing a single binop node with a
22 // JSOperator. This class manages the rewriting of context, control, and effect
23 // dependencies during lowering of a binop and contains numerous helper
24 // functions for matching the types of inputs to an operation.
25 class JSBinopReduction final {
26  public:
JSBinopReduction(JSTypedLowering * lowering,Node * node)27   JSBinopReduction(JSTypedLowering* lowering, Node* node)
28       : lowering_(lowering), node_(node) {}
29 
GetNumberBinaryOperationFeedback()30   BinaryOperationHints::Hint GetNumberBinaryOperationFeedback() {
31     if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
32         !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
33       return BinaryOperationHints::kAny;
34     }
35     DCHECK_NE(0, node_->op()->ControlOutputCount());
36     DCHECK_EQ(1, node_->op()->EffectOutputCount());
37     DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
38     BinaryOperationHints hints = BinaryOperationHintsOf(node_->op());
39     BinaryOperationHints::Hint combined = hints.combined();
40     if (combined == BinaryOperationHints::kSignedSmall ||
41         combined == BinaryOperationHints::kSigned32 ||
42         combined == BinaryOperationHints::kNumberOrUndefined) {
43       return combined;
44     }
45     return BinaryOperationHints::kAny;
46   }
47 
GetNumberCompareOperationFeedback()48   CompareOperationHints::Hint GetNumberCompareOperationFeedback() {
49     if (!(lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) ||
50         !(lowering_->flags() & JSTypedLowering::kTypeFeedbackEnabled)) {
51       return CompareOperationHints::kAny;
52     }
53     DCHECK_NE(0, node_->op()->ControlOutputCount());
54     DCHECK_EQ(1, node_->op()->EffectOutputCount());
55     DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
56     CompareOperationHints hints = CompareOperationHintsOf(node_->op());
57     CompareOperationHints::Hint combined = hints.combined();
58     if (combined == CompareOperationHints::kSignedSmall ||
59         combined == CompareOperationHints::kNumber) {
60       return combined;
61     }
62     return CompareOperationHints::kAny;
63   }
64 
ConvertInputsToNumber(Node * frame_state)65   void ConvertInputsToNumber(Node* frame_state) {
66     // To convert the inputs to numbers, we have to provide frame states
67     // for lazy bailouts in the ToNumber conversions.
68     // We use a little hack here: we take the frame state before the binary
69     // operation and use it to construct the frame states for the conversion
70     // so that after the deoptimization, the binary operation IC gets
71     // already converted values from full code. This way we are sure that we
72     // will not re-do any of the side effects.
73 
74     Node* left_input = nullptr;
75     Node* right_input = nullptr;
76     bool left_is_primitive = left_type()->Is(Type::PlainPrimitive());
77     bool right_is_primitive = right_type()->Is(Type::PlainPrimitive());
78     bool handles_exception = NodeProperties::IsExceptionalCall(node_);
79 
80     if (!left_is_primitive && !right_is_primitive && handles_exception) {
81       ConvertBothInputsToNumber(&left_input, &right_input, frame_state);
82     } else {
83       left_input = left_is_primitive
84                        ? ConvertPlainPrimitiveToNumber(left())
85                        : ConvertSingleInputToNumber(
86                              left(), CreateFrameStateForLeftInput(frame_state));
87       right_input = right_is_primitive
88                         ? ConvertPlainPrimitiveToNumber(right())
89                         : ConvertSingleInputToNumber(
90                               right(), CreateFrameStateForRightInput(
91                                            frame_state, left_input));
92     }
93 
94     node_->ReplaceInput(0, left_input);
95     node_->ReplaceInput(1, right_input);
96   }
97 
ConvertInputsToUI32(Signedness left_signedness,Signedness right_signedness)98   void ConvertInputsToUI32(Signedness left_signedness,
99                            Signedness right_signedness) {
100     node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness));
101     node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness));
102   }
103 
SwapInputs()104   void SwapInputs() {
105     Node* l = left();
106     Node* r = right();
107     node_->ReplaceInput(0, r);
108     node_->ReplaceInput(1, l);
109   }
110 
111   // Remove all effect and control inputs and outputs to this node and change
112   // to the pure operator {op}, possibly inserting a boolean inversion.
ChangeToPureOperator(const Operator * op,bool invert=false,Type * type=Type::Any ())113   Reduction ChangeToPureOperator(const Operator* op, bool invert = false,
114                                  Type* type = Type::Any()) {
115     DCHECK_EQ(0, op->EffectInputCount());
116     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
117     DCHECK_EQ(0, op->ControlInputCount());
118     DCHECK_EQ(2, op->ValueInputCount());
119 
120     // Remove the effects from the node, and update its effect/control usages.
121     if (node_->op()->EffectInputCount() > 0) {
122       lowering_->RelaxEffectsAndControls(node_);
123     }
124     // Remove the inputs corresponding to context, effect, and control.
125     NodeProperties::RemoveNonValueInputs(node_);
126     // Finally, update the operator to the new one.
127     NodeProperties::ChangeOp(node_, op);
128 
129     // TODO(jarin): Replace the explicit typing hack with a call to some method
130     // that encapsulates changing the operator and re-typing.
131     Type* node_type = NodeProperties::GetType(node_);
132     NodeProperties::SetType(node_, Type::Intersect(node_type, type, zone()));
133 
134     if (invert) {
135       // Insert an boolean not to invert the value.
136       Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
137       node_->ReplaceUses(value);
138       // Note: ReplaceUses() smashes all uses, so smash it back here.
139       value->ReplaceInput(0, node_);
140       return lowering_->Replace(value);
141     }
142     return lowering_->Changed(node_);
143   }
144 
ChangeToSpeculativeOperator(const Operator * op,Type * upper_bound)145   Reduction ChangeToSpeculativeOperator(const Operator* op, Type* upper_bound) {
146     DCHECK_EQ(1, op->EffectInputCount());
147     DCHECK_EQ(1, op->EffectOutputCount());
148     DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
149     DCHECK_EQ(1, op->ControlInputCount());
150     DCHECK_EQ(0, op->ControlOutputCount());
151     DCHECK_EQ(0, OperatorProperties::GetFrameStateInputCount(op));
152     DCHECK_EQ(2, op->ValueInputCount());
153 
154     DCHECK_EQ(1, node_->op()->EffectInputCount());
155     DCHECK_EQ(1, node_->op()->EffectOutputCount());
156     DCHECK_EQ(1, node_->op()->ControlInputCount());
157     DCHECK_LT(1, node_->op()->ControlOutputCount());
158     DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node_->op()));
159     DCHECK_EQ(2, node_->op()->ValueInputCount());
160 
161     // Reconnect the control output to bypass the IfSuccess node and
162     // possibly disconnect from the IfException node.
163     for (Edge edge : node_->use_edges()) {
164       Node* const user = edge.from();
165       DCHECK(!user->IsDead());
166       if (NodeProperties::IsControlEdge(edge)) {
167         if (user->opcode() == IrOpcode::kIfSuccess) {
168           user->ReplaceUses(NodeProperties::GetControlInput(node_));
169           user->Kill();
170         } else {
171           DCHECK_EQ(user->opcode(), IrOpcode::kIfException);
172           edge.UpdateTo(jsgraph()->Dead());
173         }
174       }
175     }
176 
177     // Remove both bailout frame states and the context.
178     node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_) + 1);
179     node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
180     node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
181 
182     NodeProperties::ChangeOp(node_, op);
183 
184     // Update the type to number.
185     Type* node_type = NodeProperties::GetType(node_);
186     NodeProperties::SetType(node_,
187                             Type::Intersect(node_type, upper_bound, zone()));
188 
189     return lowering_->Changed(node_);
190   }
191 
ChangeToPureOperator(const Operator * op,Type * type)192   Reduction ChangeToPureOperator(const Operator* op, Type* type) {
193     return ChangeToPureOperator(op, false, type);
194   }
195 
LeftInputIs(Type * t)196   bool LeftInputIs(Type* t) { return left_type()->Is(t); }
197 
RightInputIs(Type * t)198   bool RightInputIs(Type* t) { return right_type()->Is(t); }
199 
OneInputIs(Type * t)200   bool OneInputIs(Type* t) { return LeftInputIs(t) || RightInputIs(t); }
201 
BothInputsAre(Type * t)202   bool BothInputsAre(Type* t) { return LeftInputIs(t) && RightInputIs(t); }
203 
OneInputCannotBe(Type * t)204   bool OneInputCannotBe(Type* t) {
205     return !left_type()->Maybe(t) || !right_type()->Maybe(t);
206   }
207 
NeitherInputCanBe(Type * t)208   bool NeitherInputCanBe(Type* t) {
209     return !left_type()->Maybe(t) && !right_type()->Maybe(t);
210   }
211 
effect()212   Node* effect() { return NodeProperties::GetEffectInput(node_); }
control()213   Node* control() { return NodeProperties::GetControlInput(node_); }
context()214   Node* context() { return NodeProperties::GetContextInput(node_); }
left()215   Node* left() { return NodeProperties::GetValueInput(node_, 0); }
right()216   Node* right() { return NodeProperties::GetValueInput(node_, 1); }
left_type()217   Type* left_type() { return NodeProperties::GetType(node_->InputAt(0)); }
right_type()218   Type* right_type() { return NodeProperties::GetType(node_->InputAt(1)); }
219 
simplified()220   SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
graph() const221   Graph* graph() const { return lowering_->graph(); }
jsgraph()222   JSGraph* jsgraph() { return lowering_->jsgraph(); }
javascript()223   JSOperatorBuilder* javascript() { return lowering_->javascript(); }
machine()224   MachineOperatorBuilder* machine() { return lowering_->machine(); }
common()225   CommonOperatorBuilder* common() { return jsgraph()->common(); }
zone() const226   Zone* zone() const { return graph()->zone(); }
227 
228  private:
229   JSTypedLowering* lowering_;  // The containing lowering instance.
230   Node* node_;                 // The original node.
231 
CreateFrameStateForLeftInput(Node * frame_state)232   Node* CreateFrameStateForLeftInput(Node* frame_state) {
233     FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
234 
235     if (state_info.bailout_id() == BailoutId::None()) {
236       // Dummy frame state => just leave it as is.
237       return frame_state;
238     }
239 
240     // If the frame state is already the right one, just return it.
241     if (state_info.state_combine().kind() == OutputFrameStateCombine::kPokeAt &&
242         state_info.state_combine().GetOffsetToPokeAt() == 1) {
243       return frame_state;
244     }
245 
246     // Here, we smash the result of the conversion into the slot just below
247     // the stack top. This is the slot that full code uses to store the
248     // left operand.
249     const Operator* op = jsgraph()->common()->FrameState(
250         state_info.bailout_id(), OutputFrameStateCombine::PokeAt(1),
251         state_info.function_info());
252 
253     return graph()->NewNode(op,
254                             frame_state->InputAt(kFrameStateParametersInput),
255                             frame_state->InputAt(kFrameStateLocalsInput),
256                             frame_state->InputAt(kFrameStateStackInput),
257                             frame_state->InputAt(kFrameStateContextInput),
258                             frame_state->InputAt(kFrameStateFunctionInput),
259                             frame_state->InputAt(kFrameStateOuterStateInput));
260   }
261 
CreateFrameStateForRightInput(Node * frame_state,Node * converted_left)262   Node* CreateFrameStateForRightInput(Node* frame_state, Node* converted_left) {
263     FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state);
264 
265     if (state_info.bailout_id() == BailoutId::None()) {
266       // Dummy frame state => just leave it as is.
267       return frame_state;
268     }
269 
270     // Create a frame state that stores the result of the operation to the
271     // top of the stack (i.e., the slot used for the right operand).
272     const Operator* op = jsgraph()->common()->FrameState(
273         state_info.bailout_id(), OutputFrameStateCombine::PokeAt(0),
274         state_info.function_info());
275 
276     // Change the left operand {converted_left} on the expression stack.
277     Node* stack = frame_state->InputAt(2);
278     DCHECK_EQ(stack->opcode(), IrOpcode::kStateValues);
279     DCHECK_GE(stack->InputCount(), 2);
280 
281     // TODO(jarin) Allocate in a local zone or a reusable buffer.
282     NodeVector new_values(stack->InputCount(), zone());
283     for (int i = 0; i < stack->InputCount(); i++) {
284       if (i == stack->InputCount() - 2) {
285         new_values[i] = converted_left;
286       } else {
287         new_values[i] = stack->InputAt(i);
288       }
289     }
290     Node* new_stack =
291         graph()->NewNode(stack->op(), stack->InputCount(), &new_values.front());
292 
293     return graph()->NewNode(
294         op, frame_state->InputAt(kFrameStateParametersInput),
295         frame_state->InputAt(kFrameStateLocalsInput), new_stack,
296         frame_state->InputAt(kFrameStateContextInput),
297         frame_state->InputAt(kFrameStateFunctionInput),
298         frame_state->InputAt(kFrameStateOuterStateInput));
299   }
300 
ConvertPlainPrimitiveToNumber(Node * node)301   Node* ConvertPlainPrimitiveToNumber(Node* node) {
302     DCHECK(NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
303     // Avoid inserting too many eager ToNumber() operations.
304     Reduction const reduction = lowering_->ReduceJSToNumberInput(node);
305     if (reduction.Changed()) return reduction.replacement();
306     if (NodeProperties::GetType(node)->Is(Type::Number())) {
307       return node;
308     }
309     return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), node);
310   }
311 
ConvertSingleInputToNumber(Node * node,Node * frame_state)312   Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) {
313     DCHECK(!NodeProperties::GetType(node)->Is(Type::PlainPrimitive()));
314     Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(),
315                                      frame_state, effect(), control());
316     Node* const if_success = graph()->NewNode(common()->IfSuccess(), n);
317     NodeProperties::ReplaceControlInput(node_, if_success);
318     NodeProperties::ReplaceUses(node_, node_, node_, node_, n);
319     update_effect(n);
320     return n;
321   }
322 
ConvertBothInputsToNumber(Node ** left_result,Node ** right_result,Node * frame_state)323   void ConvertBothInputsToNumber(Node** left_result, Node** right_result,
324                                  Node* frame_state) {
325     Node* projections[2];
326 
327     // Find {IfSuccess} and {IfException} continuations of the operation.
328     NodeProperties::CollectControlProjections(node_, projections, 2);
329     IfExceptionHint hint = OpParameter<IfExceptionHint>(projections[1]);
330     Node* if_exception = projections[1];
331     Node* if_success = projections[0];
332 
333     // Insert two ToNumber() operations that both potentially throw.
334     Node* left_state = CreateFrameStateForLeftInput(frame_state);
335     Node* left_conv =
336         graph()->NewNode(javascript()->ToNumber(), left(), context(),
337                          left_state, effect(), control());
338     Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv);
339     Node* right_state = CreateFrameStateForRightInput(frame_state, left_conv);
340     Node* right_conv =
341         graph()->NewNode(javascript()->ToNumber(), right(), context(),
342                          right_state, left_conv, left_success);
343     Node* left_exception =
344         graph()->NewNode(common()->IfException(hint), left_conv, left_conv);
345     Node* right_exception =
346         graph()->NewNode(common()->IfException(hint), right_conv, right_conv);
347     NodeProperties::ReplaceControlInput(if_success, right_conv);
348     update_effect(right_conv);
349 
350     // Wire conversions to existing {IfException} continuation.
351     Node* exception_merge = if_exception;
352     Node* exception_value =
353         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
354                          left_exception, right_exception, exception_merge);
355     Node* exception_effect =
356         graph()->NewNode(common()->EffectPhi(2), left_exception,
357                          right_exception, exception_merge);
358     for (Edge edge : exception_merge->use_edges()) {
359       if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect);
360       if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value);
361     }
362     NodeProperties::RemoveType(exception_merge);
363     exception_merge->ReplaceInput(0, left_exception);
364     exception_merge->ReplaceInput(1, right_exception);
365     NodeProperties::ChangeOp(exception_merge, common()->Merge(2));
366 
367     *left_result = left_conv;
368     *right_result = right_conv;
369   }
370 
ConvertToUI32(Node * node,Signedness signedness)371   Node* ConvertToUI32(Node* node, Signedness signedness) {
372     // Avoid introducing too many eager NumberToXXnt32() operations.
373     Type* type = NodeProperties::GetType(node);
374     if (signedness == kSigned) {
375       if (!type->Is(Type::Signed32())) {
376         node = graph()->NewNode(simplified()->NumberToInt32(), node);
377       }
378     } else {
379       DCHECK_EQ(kUnsigned, signedness);
380       if (!type->Is(Type::Unsigned32())) {
381         node = graph()->NewNode(simplified()->NumberToUint32(), node);
382       }
383     }
384     return node;
385   }
386 
update_effect(Node * effect)387   void update_effect(Node* effect) {
388     NodeProperties::ReplaceEffectInput(node_, effect);
389   }
390 };
391 
392 
393 // TODO(turbofan): js-typed-lowering improvements possible
394 // - immediately put in type bounds for all new nodes
395 // - relax effects from generic but not-side-effecting operations
396 
397 
JSTypedLowering(Editor * editor,CompilationDependencies * dependencies,Flags flags,JSGraph * jsgraph,Zone * zone)398 JSTypedLowering::JSTypedLowering(Editor* editor,
399                                  CompilationDependencies* dependencies,
400                                  Flags flags, JSGraph* jsgraph, Zone* zone)
401     : AdvancedReducer(editor),
402       dependencies_(dependencies),
403       flags_(flags),
404       jsgraph_(jsgraph),
405       true_type_(Type::Constant(factory()->true_value(), graph()->zone())),
406       false_type_(Type::Constant(factory()->false_value(), graph()->zone())),
407       the_hole_type_(
408           Type::Constant(factory()->the_hole_value(), graph()->zone())),
409       type_cache_(TypeCache::Get()) {
410   for (size_t k = 0; k < arraysize(shifted_int32_ranges_); ++k) {
411     double min = kMinInt / (1 << k);
412     double max = kMaxInt / (1 << k);
413     shifted_int32_ranges_[k] = Type::Range(min, max, graph()->zone());
414   }
415 }
416 
417 
ReduceJSAdd(Node * node)418 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
419   if (flags() & kDisableBinaryOpReduction) return NoChange();
420 
421   JSBinopReduction r(this, node);
422 
423   BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
424   if (feedback == BinaryOperationHints::kNumberOrUndefined &&
425       r.BothInputsAre(Type::PlainPrimitive()) &&
426       r.NeitherInputCanBe(Type::StringOrReceiver())) {
427     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
428     Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
429     r.ConvertInputsToNumber(frame_state);
430     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
431   }
432   if (feedback != BinaryOperationHints::kAny) {
433     // Lower to the optimistic number binop.
434     return r.ChangeToSpeculativeOperator(
435         simplified()->SpeculativeNumberAdd(feedback), Type::Number());
436   }
437   if (r.BothInputsAre(Type::Number())) {
438     // JSAdd(x:number, y:number) => NumberAdd(x, y)
439     Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
440     r.ConvertInputsToNumber(frame_state);
441     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
442   }
443   if (r.NeitherInputCanBe(Type::StringOrReceiver())) {
444     // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
445     Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
446     r.ConvertInputsToNumber(frame_state);
447     return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number());
448   }
449   if (r.OneInputIs(Type::String())) {
450     StringAddFlags flags = STRING_ADD_CHECK_NONE;
451     if (!r.LeftInputIs(Type::String())) {
452       flags = STRING_ADD_CONVERT_LEFT;
453     } else if (!r.RightInputIs(Type::String())) {
454       flags = STRING_ADD_CONVERT_RIGHT;
455     }
456     // JSAdd(x:string, y) => CallStub[StringAdd](x, y)
457     // JSAdd(x, y:string) => CallStub[StringAdd](x, y)
458     Callable const callable =
459         CodeFactory::StringAdd(isolate(), flags, NOT_TENURED);
460     CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
461         isolate(), graph()->zone(), callable.descriptor(), 0,
462         CallDescriptor::kNeedsFrameState, node->op()->properties());
463     DCHECK_EQ(2, OperatorProperties::GetFrameStateInputCount(node->op()));
464     node->RemoveInput(NodeProperties::FirstFrameStateIndex(node) + 1);
465     node->InsertInput(graph()->zone(), 0,
466                       jsgraph()->HeapConstant(callable.code()));
467     NodeProperties::ChangeOp(node, common()->Call(desc));
468     return Changed(node);
469   }
470   return NoChange();
471 }
472 
473 
ReduceJSModulus(Node * node)474 Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
475   if (flags() & kDisableBinaryOpReduction) return NoChange();
476   JSBinopReduction r(this, node);
477   if (r.BothInputsAre(Type::Number())) {
478     // JSModulus(x:number, x:number) => NumberModulus(x, y)
479     return r.ChangeToPureOperator(simplified()->NumberModulus(),
480                                   Type::Number());
481   }
482   BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
483   if (feedback != BinaryOperationHints::kAny) {
484     return r.ChangeToSpeculativeOperator(
485         simplified()->SpeculativeNumberModulus(feedback), Type::Number());
486   }
487   return NoChange();
488 }
489 
ReduceJSSubtract(Node * node)490 Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
491   if (flags() & kDisableBinaryOpReduction) return NoChange();
492   JSBinopReduction r(this, node);
493   BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
494   if (feedback == BinaryOperationHints::kNumberOrUndefined &&
495       r.BothInputsAre(Type::PlainPrimitive())) {
496     // JSSubtract(x:plain-primitive, y:plain-primitive)
497     //   => NumberSubtract(ToNumber(x), ToNumber(y))
498     Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
499     r.ConvertInputsToNumber(frame_state);
500     return r.ChangeToPureOperator(simplified()->NumberSubtract(),
501                                   Type::Number());
502   }
503   if (feedback != BinaryOperationHints::kAny) {
504     // Lower to the optimistic number binop.
505     return r.ChangeToSpeculativeOperator(
506         simplified()->SpeculativeNumberSubtract(feedback), Type::Number());
507   }
508   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
509   r.ConvertInputsToNumber(frame_state);
510   return r.ChangeToPureOperator(simplified()->NumberSubtract(), Type::Number());
511 }
512 
ReduceJSMultiply(Node * node)513 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
514   if (flags() & kDisableBinaryOpReduction) return NoChange();
515   JSBinopReduction r(this, node);
516 
517   BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
518   if (feedback != BinaryOperationHints::kAny) {
519     return r.ChangeToSpeculativeOperator(
520         simplified()->SpeculativeNumberMultiply(feedback), Type::Number());
521   }
522 
523   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
524   r.ConvertInputsToNumber(frame_state);
525   return r.ChangeToPureOperator(simplified()->NumberMultiply(), Type::Number());
526 }
527 
ReduceJSDivide(Node * node)528 Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
529   if (flags() & kDisableBinaryOpReduction) return NoChange();
530   JSBinopReduction r(this, node);
531   BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
532   if (feedback != BinaryOperationHints::kAny) {
533     return r.ChangeToSpeculativeOperator(
534         simplified()->SpeculativeNumberDivide(feedback), Type::Number());
535   }
536   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
537   r.ConvertInputsToNumber(frame_state);
538   return r.ChangeToPureOperator(simplified()->NumberDivide(), Type::Number());
539 }
540 
541 
ReduceInt32Binop(Node * node,const Operator * intOp)542 Reduction JSTypedLowering::ReduceInt32Binop(Node* node, const Operator* intOp) {
543   if (flags() & kDisableBinaryOpReduction) return NoChange();
544 
545   JSBinopReduction r(this, node);
546   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
547   r.ConvertInputsToNumber(frame_state);
548   r.ConvertInputsToUI32(kSigned, kSigned);
549   return r.ChangeToPureOperator(intOp, Type::Integral32());
550 }
551 
552 
ReduceUI32Shift(Node * node,Signedness left_signedness,const Operator * shift_op)553 Reduction JSTypedLowering::ReduceUI32Shift(Node* node,
554                                            Signedness left_signedness,
555                                            const Operator* shift_op) {
556   if (flags() & kDisableBinaryOpReduction) return NoChange();
557 
558   JSBinopReduction r(this, node);
559   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
560   r.ConvertInputsToNumber(frame_state);
561   r.ConvertInputsToUI32(left_signedness, kUnsigned);
562   return r.ChangeToPureOperator(shift_op);
563 }
564 
565 
ReduceJSComparison(Node * node)566 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
567   if (flags() & kDisableBinaryOpReduction) return NoChange();
568 
569   JSBinopReduction r(this, node);
570   if (r.BothInputsAre(Type::String())) {
571     // If both inputs are definitely strings, perform a string comparison.
572     const Operator* stringOp;
573     switch (node->opcode()) {
574       case IrOpcode::kJSLessThan:
575         stringOp = simplified()->StringLessThan();
576         break;
577       case IrOpcode::kJSGreaterThan:
578         stringOp = simplified()->StringLessThan();
579         r.SwapInputs();  // a > b => b < a
580         break;
581       case IrOpcode::kJSLessThanOrEqual:
582         stringOp = simplified()->StringLessThanOrEqual();
583         break;
584       case IrOpcode::kJSGreaterThanOrEqual:
585         stringOp = simplified()->StringLessThanOrEqual();
586         r.SwapInputs();  // a >= b => b <= a
587         break;
588       default:
589         return NoChange();
590     }
591     r.ChangeToPureOperator(stringOp);
592     return Changed(node);
593   }
594 
595   CompareOperationHints::Hint hint = r.GetNumberCompareOperationFeedback();
596   if (hint != CompareOperationHints::kAny ||
597       r.OneInputCannotBe(Type::StringOrReceiver())) {
598     const Operator* less_than;
599     const Operator* less_than_or_equal;
600     if (r.BothInputsAre(Type::Unsigned32())) {
601       less_than = machine()->Uint32LessThan();
602       less_than_or_equal = machine()->Uint32LessThanOrEqual();
603     } else if (r.BothInputsAre(Type::Signed32())) {
604       less_than = machine()->Int32LessThan();
605       less_than_or_equal = machine()->Int32LessThanOrEqual();
606     } else if (hint != CompareOperationHints::kAny) {
607       less_than = simplified()->SpeculativeNumberLessThan(hint);
608       less_than_or_equal = simplified()->SpeculativeNumberLessThanOrEqual(hint);
609     } else {
610       // TODO(turbofan): mixed signed/unsigned int32 comparisons.
611       Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
612       r.ConvertInputsToNumber(frame_state);
613       less_than = simplified()->NumberLessThan();
614       less_than_or_equal = simplified()->NumberLessThanOrEqual();
615     }
616     const Operator* comparison;
617     switch (node->opcode()) {
618       case IrOpcode::kJSLessThan:
619         comparison = less_than;
620         break;
621       case IrOpcode::kJSGreaterThan:
622         comparison = less_than;
623         r.SwapInputs();  // a > b => b < a
624         break;
625       case IrOpcode::kJSLessThanOrEqual:
626         comparison = less_than_or_equal;
627         break;
628       case IrOpcode::kJSGreaterThanOrEqual:
629         comparison = less_than_or_equal;
630         r.SwapInputs();  // a >= b => b <= a
631         break;
632       default:
633         return NoChange();
634     }
635     if (comparison->EffectInputCount() > 0) {
636       return r.ChangeToSpeculativeOperator(comparison, Type::Boolean());
637     } else {
638       return r.ChangeToPureOperator(comparison);
639     }
640   }
641   // TODO(turbofan): relax/remove effects of this operator in other cases.
642   return NoChange();  // Keep a generic comparison.
643 }
644 
ReduceJSEqualTypeOf(Node * node,bool invert)645 Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
646   HeapObjectBinopMatcher m(node);
647   if (m.left().IsJSTypeOf() && m.right().HasValue() &&
648       m.right().Value()->IsString()) {
649     Node* replacement;
650     Node* input = m.left().InputAt(0);
651     Handle<String> value = Handle<String>::cast(m.right().Value());
652     if (String::Equals(value, factory()->boolean_string())) {
653       replacement = graph()->NewNode(
654           common()->Select(MachineRepresentation::kTagged),
655           graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
656                            jsgraph()->TrueConstant()),
657           jsgraph()->TrueConstant(),
658           graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
659                            jsgraph()->FalseConstant()));
660     } else if (String::Equals(value, factory()->function_string())) {
661       replacement = graph()->NewNode(simplified()->ObjectIsCallable(), input);
662     } else if (String::Equals(value, factory()->number_string())) {
663       replacement = graph()->NewNode(simplified()->ObjectIsNumber(), input);
664     } else if (String::Equals(value, factory()->string_string())) {
665       replacement = graph()->NewNode(simplified()->ObjectIsString(), input);
666     } else if (String::Equals(value, factory()->undefined_string())) {
667       replacement = graph()->NewNode(
668           common()->Select(MachineRepresentation::kTagged),
669           graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), input,
670                            jsgraph()->NullConstant()),
671           jsgraph()->FalseConstant(),
672           graph()->NewNode(simplified()->ObjectIsUndetectable(), input));
673     } else {
674       return NoChange();
675     }
676     if (invert) {
677       replacement = graph()->NewNode(simplified()->BooleanNot(), replacement);
678     }
679     return Replace(replacement);
680   }
681   return NoChange();
682 }
683 
ReduceJSEqual(Node * node,bool invert)684 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
685   if (flags() & kDisableBinaryOpReduction) return NoChange();
686 
687   Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
688   if (reduction.Changed()) {
689     ReplaceWithValue(node, reduction.replacement());
690     return reduction;
691   }
692 
693   JSBinopReduction r(this, node);
694 
695   if (r.BothInputsAre(Type::Number())) {
696     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
697   }
698   if (r.BothInputsAre(Type::String())) {
699     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
700   }
701   if (r.BothInputsAre(Type::Boolean())) {
702     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
703                                   invert);
704   }
705   if (r.BothInputsAre(Type::Receiver())) {
706     return r.ChangeToPureOperator(
707         simplified()->ReferenceEqual(Type::Receiver()), invert);
708   }
709   if (r.OneInputIs(Type::Undetectable())) {
710     RelaxEffectsAndControls(node);
711     node->RemoveInput(r.LeftInputIs(Type::Undetectable()) ? 0 : 1);
712     node->TrimInputCount(1);
713     NodeProperties::ChangeOp(node, simplified()->ObjectIsUndetectable());
714     if (invert) {
715       // Insert an boolean not to invert the value.
716       Node* value = graph()->NewNode(simplified()->BooleanNot(), node);
717       node->ReplaceUses(value);
718       // Note: ReplaceUses() smashes all uses, so smash it back here.
719       value->ReplaceInput(0, node);
720       return Replace(value);
721     }
722     return Changed(node);
723   }
724   return NoChange();
725 }
726 
727 
ReduceJSStrictEqual(Node * node,bool invert)728 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
729   if (flags() & kDisableBinaryOpReduction) return NoChange();
730 
731   JSBinopReduction r(this, node);
732   if (r.left() == r.right()) {
733     // x === x is always true if x != NaN
734     if (!r.left_type()->Maybe(Type::NaN())) {
735       Node* replacement = jsgraph()->BooleanConstant(!invert);
736       ReplaceWithValue(node, replacement);
737       return Replace(replacement);
738     }
739   }
740   if (r.OneInputCannotBe(Type::NumberOrSimdOrString())) {
741     // For values with canonical representation (i.e. neither String, nor
742     // Simd128Value nor Number) an empty type intersection means the values
743     // cannot be strictly equal.
744     if (!r.left_type()->Maybe(r.right_type())) {
745       Node* replacement = jsgraph()->BooleanConstant(invert);
746       ReplaceWithValue(node, replacement);
747       return Replace(replacement);
748     }
749   }
750   Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
751   if (reduction.Changed()) {
752     return reduction;
753   }
754   if (r.OneInputIs(the_hole_type_)) {
755     return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_),
756                                   invert);
757   }
758   if (r.OneInputIs(Type::Undefined())) {
759     return r.ChangeToPureOperator(
760         simplified()->ReferenceEqual(Type::Undefined()), invert);
761   }
762   if (r.OneInputIs(Type::Null())) {
763     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
764                                   invert);
765   }
766   if (r.OneInputIs(Type::Boolean())) {
767     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
768                                   invert);
769   }
770   if (r.OneInputIs(Type::Object())) {
771     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
772                                   invert);
773   }
774   if (r.OneInputIs(Type::Receiver())) {
775     return r.ChangeToPureOperator(
776         simplified()->ReferenceEqual(Type::Receiver()), invert);
777   }
778   if (r.BothInputsAre(Type::Unique())) {
779     return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()),
780                                   invert);
781   }
782   if (r.BothInputsAre(Type::String())) {
783     return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
784   }
785   if (r.BothInputsAre(Type::Number())) {
786     return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
787   }
788   // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
789   return NoChange();
790 }
791 
792 
ReduceJSToBoolean(Node * node)793 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) {
794   Node* const input = node->InputAt(0);
795   Type* const input_type = NodeProperties::GetType(input);
796   if (input_type->Is(Type::Boolean())) {
797     // JSToBoolean(x:boolean) => x
798     return Replace(input);
799   } else if (input_type->Is(Type::OrderedNumber())) {
800     // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x,#0))
801     RelaxEffectsAndControls(node);
802     node->ReplaceInput(0, graph()->NewNode(simplified()->NumberEqual(), input,
803                                            jsgraph()->ZeroConstant()));
804     node->TrimInputCount(1);
805     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
806     return Changed(node);
807   } else if (input_type->Is(Type::String())) {
808     // JSToBoolean(x:string) => NumberLessThan(#0,x.length)
809     FieldAccess const access = AccessBuilder::ForStringLength();
810     Node* length = graph()->NewNode(simplified()->LoadField(access), input,
811                                     graph()->start(), graph()->start());
812     ReplaceWithValue(node, node, length);
813     node->ReplaceInput(0, jsgraph()->ZeroConstant());
814     node->ReplaceInput(1, length);
815     NodeProperties::ChangeOp(node, simplified()->NumberLessThan());
816     return Changed(node);
817   }
818   return NoChange();
819 }
820 
ReduceJSToInteger(Node * node)821 Reduction JSTypedLowering::ReduceJSToInteger(Node* node) {
822   Node* const input = NodeProperties::GetValueInput(node, 0);
823   Type* const input_type = NodeProperties::GetType(input);
824   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
825     // JSToInteger(x:integer) => x
826     ReplaceWithValue(node, input);
827     return Replace(input);
828   }
829   return NoChange();
830 }
831 
ReduceJSToLength(Node * node)832 Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
833   Node* input = NodeProperties::GetValueInput(node, 0);
834   Type* input_type = NodeProperties::GetType(input);
835   if (input_type->Is(type_cache_.kIntegerOrMinusZero)) {
836     if (input_type->Max() <= 0.0) {
837       input = jsgraph()->ZeroConstant();
838     } else if (input_type->Min() >= kMaxSafeInteger) {
839       input = jsgraph()->Constant(kMaxSafeInteger);
840     } else {
841       if (input_type->Min() <= 0.0) {
842         input = graph()->NewNode(
843             common()->Select(MachineRepresentation::kTagged),
844             graph()->NewNode(simplified()->NumberLessThanOrEqual(), input,
845                              jsgraph()->ZeroConstant()),
846             jsgraph()->ZeroConstant(), input);
847         input_type = Type::Range(0.0, input_type->Max(), graph()->zone());
848         NodeProperties::SetType(input, input_type);
849       }
850       if (input_type->Max() > kMaxSafeInteger) {
851         input = graph()->NewNode(
852             common()->Select(MachineRepresentation::kTagged),
853             graph()->NewNode(simplified()->NumberLessThanOrEqual(),
854                              jsgraph()->Constant(kMaxSafeInteger), input),
855             jsgraph()->Constant(kMaxSafeInteger), input);
856         input_type =
857             Type::Range(input_type->Min(), kMaxSafeInteger, graph()->zone());
858         NodeProperties::SetType(input, input_type);
859       }
860     }
861     ReplaceWithValue(node, input);
862     return Replace(input);
863   }
864   return NoChange();
865 }
866 
ReduceJSToNumberInput(Node * input)867 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
868   // Try constant-folding of JSToNumber with constant inputs.
869   Type* input_type = NodeProperties::GetType(input);
870   if (input_type->IsConstant()) {
871     Handle<Object> input_value = input_type->AsConstant()->Value();
872     if (input_value->IsString()) {
873       return Replace(jsgraph()->Constant(
874           String::ToNumber(Handle<String>::cast(input_value))));
875     } else if (input_value->IsOddball()) {
876       return Replace(jsgraph()->Constant(
877           Oddball::ToNumber(Handle<Oddball>::cast(input_value))));
878     }
879   }
880   if (input_type->Is(Type::Number())) {
881     // JSToNumber(x:number) => x
882     return Changed(input);
883   }
884   if (input_type->Is(Type::Undefined())) {
885     // JSToNumber(undefined) => #NaN
886     return Replace(jsgraph()->NaNConstant());
887   }
888   if (input_type->Is(Type::Null())) {
889     // JSToNumber(null) => #0
890     return Replace(jsgraph()->ZeroConstant());
891   }
892   if (input_type->Is(Type::Boolean())) {
893     // JSToNumber(x:boolean) => BooleanToNumber(x)
894     return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
895   }
896   if (input_type->Is(Type::String())) {
897     // JSToNumber(x:string) => StringToNumber(x)
898     return Replace(graph()->NewNode(simplified()->StringToNumber(), input));
899   }
900   return NoChange();
901 }
902 
903 
ReduceJSToNumber(Node * node)904 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) {
905   // Try to reduce the input first.
906   Node* const input = node->InputAt(0);
907   Reduction reduction = ReduceJSToNumberInput(input);
908   if (reduction.Changed()) {
909     ReplaceWithValue(node, reduction.replacement());
910     return reduction;
911   }
912   Type* const input_type = NodeProperties::GetType(input);
913   if (input_type->Is(Type::PlainPrimitive())) {
914     RelaxEffectsAndControls(node);
915     node->TrimInputCount(1);
916     NodeProperties::ChangeOp(node, simplified()->PlainPrimitiveToNumber());
917     return Changed(node);
918   }
919   return NoChange();
920 }
921 
922 
ReduceJSToStringInput(Node * input)923 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
924   if (input->opcode() == IrOpcode::kJSToString) {
925     // Recursively try to reduce the input first.
926     Reduction result = ReduceJSToString(input);
927     if (result.Changed()) return result;
928     return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
929   }
930   Type* input_type = NodeProperties::GetType(input);
931   if (input_type->Is(Type::String())) {
932     return Changed(input);  // JSToString(x:string) => x
933   }
934   if (input_type->Is(Type::Boolean())) {
935     return Replace(graph()->NewNode(
936         common()->Select(MachineRepresentation::kTagged), input,
937         jsgraph()->HeapConstant(factory()->true_string()),
938         jsgraph()->HeapConstant(factory()->false_string())));
939   }
940   if (input_type->Is(Type::Undefined())) {
941     return Replace(jsgraph()->HeapConstant(factory()->undefined_string()));
942   }
943   if (input_type->Is(Type::Null())) {
944     return Replace(jsgraph()->HeapConstant(factory()->null_string()));
945   }
946   // TODO(turbofan): js-typed-lowering of ToString(x:number)
947   return NoChange();
948 }
949 
950 
ReduceJSToString(Node * node)951 Reduction JSTypedLowering::ReduceJSToString(Node* node) {
952   // Try to reduce the input first.
953   Node* const input = node->InputAt(0);
954   Reduction reduction = ReduceJSToStringInput(input);
955   if (reduction.Changed()) {
956     ReplaceWithValue(node, reduction.replacement());
957     return reduction;
958   }
959   return NoChange();
960 }
961 
962 
ReduceJSToObject(Node * node)963 Reduction JSTypedLowering::ReduceJSToObject(Node* node) {
964   DCHECK_EQ(IrOpcode::kJSToObject, node->opcode());
965   Node* receiver = NodeProperties::GetValueInput(node, 0);
966   Type* receiver_type = NodeProperties::GetType(receiver);
967   Node* context = NodeProperties::GetContextInput(node);
968   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
969   Node* effect = NodeProperties::GetEffectInput(node);
970   Node* control = NodeProperties::GetControlInput(node);
971   if (!receiver_type->Is(Type::Receiver())) {
972     // TODO(bmeurer/mstarzinger): Add support for lowering inside try blocks.
973     if (receiver_type->Maybe(Type::NullOrUndefined()) &&
974         NodeProperties::IsExceptionalCall(node)) {
975       // ToObject throws for null or undefined inputs.
976       return NoChange();
977     }
978 
979     // Check whether {receiver} is a Smi.
980     Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), receiver);
981     Node* branch0 =
982         graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
983     Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
984     Node* etrue0 = effect;
985 
986     Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
987     Node* efalse0 = effect;
988 
989     // Determine the instance type of {receiver}.
990     Node* receiver_map = efalse0 =
991         graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
992                          receiver, efalse0, if_false0);
993     Node* receiver_instance_type = efalse0 = graph()->NewNode(
994         simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
995         receiver_map, efalse0, if_false0);
996 
997     // Check whether {receiver} is a spec object.
998     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
999     Node* check1 =
1000         graph()->NewNode(machine()->Uint32LessThanOrEqual(),
1001                          jsgraph()->Uint32Constant(FIRST_JS_RECEIVER_TYPE),
1002                          receiver_instance_type);
1003     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1004                                      check1, if_false0);
1005     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1006     Node* etrue1 = efalse0;
1007 
1008     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1009     Node* efalse1 = efalse0;
1010 
1011     // Convert {receiver} using the ToObjectStub.
1012     Node* if_convert =
1013         graph()->NewNode(common()->Merge(2), if_true0, if_false1);
1014     Node* econvert =
1015         graph()->NewNode(common()->EffectPhi(2), etrue0, efalse1, if_convert);
1016     Node* rconvert;
1017     {
1018       Callable callable = CodeFactory::ToObject(isolate());
1019       CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
1020           isolate(), graph()->zone(), callable.descriptor(), 0,
1021           CallDescriptor::kNeedsFrameState, node->op()->properties());
1022       rconvert = econvert = graph()->NewNode(
1023           common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1024           receiver, context, frame_state, econvert, if_convert);
1025     }
1026 
1027     // The {receiver} is already a spec object.
1028     Node* if_done = if_true1;
1029     Node* edone = etrue1;
1030     Node* rdone = receiver;
1031 
1032     control = graph()->NewNode(common()->Merge(2), if_convert, if_done);
1033     effect = graph()->NewNode(common()->EffectPhi(2), econvert, edone, control);
1034     receiver =
1035         graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1036                          rconvert, rdone, control);
1037   }
1038   ReplaceWithValue(node, receiver, effect, control);
1039   return Changed(receiver);
1040 }
1041 
1042 
ReduceJSLoadNamed(Node * node)1043 Reduction JSTypedLowering::ReduceJSLoadNamed(Node* node) {
1044   DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
1045   Node* receiver = NodeProperties::GetValueInput(node, 0);
1046   Type* receiver_type = NodeProperties::GetType(receiver);
1047   Node* effect = NodeProperties::GetEffectInput(node);
1048   Node* control = NodeProperties::GetControlInput(node);
1049   Handle<Name> name = NamedAccessOf(node->op()).name();
1050   // Optimize "length" property of strings.
1051   if (name.is_identical_to(factory()->length_string()) &&
1052       receiver_type->Is(Type::String())) {
1053     Node* value = effect = graph()->NewNode(
1054         simplified()->LoadField(AccessBuilder::ForStringLength()), receiver,
1055         effect, control);
1056     ReplaceWithValue(node, value, effect);
1057     return Replace(value);
1058   }
1059   return NoChange();
1060 }
1061 
1062 
ReduceJSLoadProperty(Node * node)1063 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
1064   Node* key = NodeProperties::GetValueInput(node, 1);
1065   Node* base = NodeProperties::GetValueInput(node, 0);
1066   Type* key_type = NodeProperties::GetType(key);
1067   HeapObjectMatcher mbase(base);
1068   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
1069     Handle<JSTypedArray> const array =
1070         Handle<JSTypedArray>::cast(mbase.Value());
1071     if (!array->GetBuffer()->was_neutered()) {
1072       array->GetBuffer()->set_is_neuterable(false);
1073       BufferAccess const access(array->type());
1074       size_t const k =
1075           ElementSizeLog2Of(access.machine_type().representation());
1076       double const byte_length = array->byte_length()->Number();
1077       CHECK_LT(k, arraysize(shifted_int32_ranges_));
1078       if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
1079         // JSLoadProperty(typed-array, int32)
1080         Handle<FixedTypedArrayBase> elements =
1081             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
1082         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
1083         Node* length = jsgraph()->Constant(byte_length);
1084         Node* effect = NodeProperties::GetEffectInput(node);
1085         Node* control = NodeProperties::GetControlInput(node);
1086         // Check if we can avoid the bounds check.
1087         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
1088           Node* load = graph()->NewNode(
1089               simplified()->LoadElement(
1090                   AccessBuilder::ForTypedArrayElement(array->type(), true)),
1091               buffer, key, effect, control);
1092           ReplaceWithValue(node, load, load);
1093           return Replace(load);
1094         }
1095         // Compute byte offset.
1096         Node* offset = Word32Shl(key, static_cast<int>(k));
1097         Node* load = graph()->NewNode(simplified()->LoadBuffer(access), buffer,
1098                                       offset, length, effect, control);
1099         ReplaceWithValue(node, load, load);
1100         return Replace(load);
1101       }
1102     }
1103   }
1104   return NoChange();
1105 }
1106 
1107 
ReduceJSStoreProperty(Node * node)1108 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
1109   Node* key = NodeProperties::GetValueInput(node, 1);
1110   Node* base = NodeProperties::GetValueInput(node, 0);
1111   Node* value = NodeProperties::GetValueInput(node, 2);
1112   Type* key_type = NodeProperties::GetType(key);
1113   Type* value_type = NodeProperties::GetType(value);
1114   HeapObjectMatcher mbase(base);
1115   if (mbase.HasValue() && mbase.Value()->IsJSTypedArray()) {
1116     Handle<JSTypedArray> const array =
1117         Handle<JSTypedArray>::cast(mbase.Value());
1118     if (!array->GetBuffer()->was_neutered()) {
1119       array->GetBuffer()->set_is_neuterable(false);
1120       BufferAccess const access(array->type());
1121       size_t const k =
1122           ElementSizeLog2Of(access.machine_type().representation());
1123       double const byte_length = array->byte_length()->Number();
1124       CHECK_LT(k, arraysize(shifted_int32_ranges_));
1125       if (access.external_array_type() != kExternalUint8ClampedArray &&
1126           key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
1127         // JSLoadProperty(typed-array, int32)
1128         Handle<FixedTypedArrayBase> elements =
1129             Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
1130         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
1131         Node* length = jsgraph()->Constant(byte_length);
1132         Node* context = NodeProperties::GetContextInput(node);
1133         Node* effect = NodeProperties::GetEffectInput(node);
1134         Node* control = NodeProperties::GetControlInput(node);
1135         // Convert to a number first.
1136         if (!value_type->Is(Type::Number())) {
1137           Reduction number_reduction = ReduceJSToNumberInput(value);
1138           if (number_reduction.Changed()) {
1139             value = number_reduction.replacement();
1140           } else {
1141             Node* frame_state_for_to_number =
1142                 NodeProperties::FindFrameStateBefore(node);
1143             value = effect =
1144                 graph()->NewNode(javascript()->ToNumber(), value, context,
1145                                  frame_state_for_to_number, effect, control);
1146           }
1147         }
1148         // Check if we can avoid the bounds check.
1149         if (key_type->Min() >= 0 && key_type->Max() < array->length_value()) {
1150           RelaxControls(node);
1151           node->ReplaceInput(0, buffer);
1152           DCHECK_EQ(key, node->InputAt(1));
1153           node->ReplaceInput(2, value);
1154           node->ReplaceInput(3, effect);
1155           node->ReplaceInput(4, control);
1156           node->TrimInputCount(5);
1157           NodeProperties::ChangeOp(
1158               node,
1159               simplified()->StoreElement(
1160                   AccessBuilder::ForTypedArrayElement(array->type(), true)));
1161           return Changed(node);
1162         }
1163         // Compute byte offset.
1164         Node* offset = Word32Shl(key, static_cast<int>(k));
1165         // Turn into a StoreBuffer operation.
1166         RelaxControls(node);
1167         node->ReplaceInput(0, buffer);
1168         node->ReplaceInput(1, offset);
1169         node->ReplaceInput(2, length);
1170         node->ReplaceInput(3, value);
1171         node->ReplaceInput(4, effect);
1172         node->ReplaceInput(5, control);
1173         node->TrimInputCount(6);
1174         NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
1175         return Changed(node);
1176       }
1177     }
1178   }
1179   return NoChange();
1180 }
1181 
1182 
ReduceJSInstanceOf(Node * node)1183 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) {
1184   DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
1185   Node* const context = NodeProperties::GetContextInput(node);
1186   Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0);
1187 
1188   // If deoptimization is disabled, we cannot optimize.
1189   if (!(flags() & kDeoptimizationEnabled)) return NoChange();
1190 
1191   // If we are in a try block, don't optimize since the runtime call
1192   // in the proxy case can throw.
1193   if (NodeProperties::IsExceptionalCall(node)) return NoChange();
1194 
1195   JSBinopReduction r(this, node);
1196   Node* effect = r.effect();
1197   Node* control = r.control();
1198 
1199   if (!r.right_type()->IsConstant() ||
1200       !r.right_type()->AsConstant()->Value()->IsJSFunction()) {
1201     return NoChange();
1202   }
1203 
1204   Handle<JSFunction> function =
1205       Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value());
1206   Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1207 
1208   // Make sure the prototype of {function} is the %FunctionPrototype%, and it
1209   // already has a meaningful initial map (i.e. we constructed at least one
1210   // instance using the constructor {function}).
1211   if (function->map()->prototype() != function->native_context()->closure() ||
1212       function->map()->has_non_instance_prototype() ||
1213       !function->has_initial_map()) {
1214     return NoChange();
1215   }
1216 
1217   // We can only use the fast case if @@hasInstance was not used so far.
1218   if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
1219   dependencies()->AssumePropertyCell(factory()->has_instance_protector());
1220 
1221   Handle<Map> initial_map(function->initial_map(), isolate());
1222   dependencies()->AssumeInitialMapCantChange(initial_map);
1223   Node* prototype =
1224       jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1225 
1226   // If the left hand side is an object, no smi check is needed.
1227   Node* is_smi = graph()->NewNode(simplified()->ObjectIsSmi(), r.left());
1228   Node* branch_is_smi =
1229       graph()->NewNode(common()->Branch(BranchHint::kFalse), is_smi, control);
1230   Node* if_is_smi = graph()->NewNode(common()->IfTrue(), branch_is_smi);
1231   Node* e_is_smi = effect;
1232   control = graph()->NewNode(common()->IfFalse(), branch_is_smi);
1233 
1234   Node* object_map = effect =
1235       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1236                        r.left(), effect, control);
1237 
1238   // Loop through the {object}s prototype chain looking for the {prototype}.
1239   Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
1240 
1241   Node* loop_effect = effect =
1242       graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1243 
1244   Node* loop_object_map =
1245       graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1246                        object_map, r.left(), loop);
1247 
1248   // Check if the lhs needs access checks.
1249   Node* map_bit_field = effect =
1250       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMapBitField()),
1251                        loop_object_map, loop_effect, control);
1252   int is_access_check_needed_bit = 1 << Map::kIsAccessCheckNeeded;
1253   Node* is_access_check_needed_num =
1254       graph()->NewNode(simplified()->NumberBitwiseAnd(), map_bit_field,
1255                        jsgraph()->Uint32Constant(is_access_check_needed_bit));
1256   Node* is_access_check_needed =
1257       graph()->NewNode(machine()->Word32Equal(), is_access_check_needed_num,
1258                        jsgraph()->Uint32Constant(is_access_check_needed_bit));
1259 
1260   Node* branch_is_access_check_needed = graph()->NewNode(
1261       common()->Branch(BranchHint::kFalse), is_access_check_needed, control);
1262   Node* if_is_access_check_needed =
1263       graph()->NewNode(common()->IfTrue(), branch_is_access_check_needed);
1264   Node* e_is_access_check_needed = effect;
1265 
1266   control =
1267       graph()->NewNode(common()->IfFalse(), branch_is_access_check_needed);
1268 
1269   // Check if the lhs is a proxy.
1270   Node* map_instance_type = effect = graph()->NewNode(
1271       simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
1272       loop_object_map, loop_effect, control);
1273   Node* is_proxy = graph()->NewNode(machine()->Word32Equal(), map_instance_type,
1274                                     jsgraph()->Uint32Constant(JS_PROXY_TYPE));
1275   Node* branch_is_proxy =
1276       graph()->NewNode(common()->Branch(BranchHint::kFalse), is_proxy, control);
1277   Node* if_is_proxy = graph()->NewNode(common()->IfTrue(), branch_is_proxy);
1278   Node* e_is_proxy = effect;
1279 
1280 
1281   Node* runtime_has_in_proto_chain = control = graph()->NewNode(
1282       common()->Merge(2), if_is_access_check_needed, if_is_proxy);
1283   effect = graph()->NewNode(common()->EffectPhi(2), e_is_access_check_needed,
1284                             e_is_proxy, control);
1285 
1286   // If we need an access check or the object is a Proxy, make a runtime call
1287   // to finish the lowering.
1288   Node* bool_result_runtime_has_in_proto_chain_case = graph()->NewNode(
1289       javascript()->CallRuntime(Runtime::kHasInPrototypeChain), r.left(),
1290       prototype, context, frame_state, effect, control);
1291 
1292   control = graph()->NewNode(common()->IfFalse(), branch_is_proxy);
1293 
1294   Node* object_prototype = effect = graph()->NewNode(
1295       simplified()->LoadField(AccessBuilder::ForMapPrototype()),
1296       loop_object_map, loop_effect, control);
1297 
1298   // If not, check if object prototype is the null prototype.
1299   Node* null_proto =
1300       graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1301                        object_prototype, jsgraph()->NullConstant());
1302   Node* branch_null_proto = graph()->NewNode(
1303       common()->Branch(BranchHint::kFalse), null_proto, control);
1304   Node* if_null_proto = graph()->NewNode(common()->IfTrue(), branch_null_proto);
1305   Node* e_null_proto = effect;
1306 
1307   control = graph()->NewNode(common()->IfFalse(), branch_null_proto);
1308 
1309   // Check if object prototype is equal to function prototype.
1310   Node* eq_proto =
1311       graph()->NewNode(simplified()->ReferenceEqual(r.right_type()),
1312                        object_prototype, prototype);
1313   Node* branch_eq_proto =
1314       graph()->NewNode(common()->Branch(BranchHint::kFalse), eq_proto, control);
1315   Node* if_eq_proto = graph()->NewNode(common()->IfTrue(), branch_eq_proto);
1316   Node* e_eq_proto = effect;
1317 
1318   control = graph()->NewNode(common()->IfFalse(), branch_eq_proto);
1319 
1320   Node* load_object_map = effect =
1321       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1322                        object_prototype, effect, control);
1323   // Close the loop.
1324   loop_effect->ReplaceInput(1, effect);
1325   loop_object_map->ReplaceInput(1, load_object_map);
1326   loop->ReplaceInput(1, control);
1327 
1328   control = graph()->NewNode(common()->Merge(3), runtime_has_in_proto_chain,
1329                              if_eq_proto, if_null_proto);
1330   effect = graph()->NewNode(common()->EffectPhi(3),
1331                             bool_result_runtime_has_in_proto_chain_case,
1332                             e_eq_proto, e_null_proto, control);
1333 
1334   Node* result = graph()->NewNode(
1335       common()->Phi(MachineRepresentation::kTagged, 3),
1336       bool_result_runtime_has_in_proto_chain_case, jsgraph()->TrueConstant(),
1337       jsgraph()->FalseConstant(), control);
1338 
1339   DCHECK_NOT_NULL(e_is_smi);
1340   control = graph()->NewNode(common()->Merge(2), if_is_smi, control);
1341   effect =
1342       graph()->NewNode(common()->EffectPhi(2), e_is_smi, effect, control);
1343   result = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1344                             jsgraph()->FalseConstant(), result, control);
1345 
1346   ReplaceWithValue(node, result, effect, control);
1347   return Changed(result);
1348 }
1349 
1350 
ReduceJSLoadContext(Node * node)1351 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
1352   DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
1353   ContextAccess const& access = ContextAccessOf(node->op());
1354   Node* effect = NodeProperties::GetEffectInput(node);
1355   Node* control = graph()->start();
1356   for (size_t i = 0; i < access.depth(); ++i) {
1357     Node* previous = effect = graph()->NewNode(
1358         simplified()->LoadField(
1359             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1360         NodeProperties::GetValueInput(node, 0), effect, control);
1361     node->ReplaceInput(0, previous);
1362   }
1363   node->ReplaceInput(1, effect);
1364   node->ReplaceInput(2, control);
1365   NodeProperties::ChangeOp(
1366       node,
1367       simplified()->LoadField(AccessBuilder::ForContextSlot(access.index())));
1368   return Changed(node);
1369 }
1370 
1371 
ReduceJSStoreContext(Node * node)1372 Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
1373   DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode());
1374   ContextAccess const& access = ContextAccessOf(node->op());
1375   Node* effect = NodeProperties::GetEffectInput(node);
1376   Node* control = graph()->start();
1377   for (size_t i = 0; i < access.depth(); ++i) {
1378     Node* previous = effect = graph()->NewNode(
1379         simplified()->LoadField(
1380             AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX)),
1381         NodeProperties::GetValueInput(node, 0), effect, control);
1382     node->ReplaceInput(0, previous);
1383   }
1384   node->RemoveInput(2);
1385   node->ReplaceInput(2, effect);
1386   NodeProperties::ChangeOp(
1387       node,
1388       simplified()->StoreField(AccessBuilder::ForContextSlot(access.index())));
1389   return Changed(node);
1390 }
1391 
1392 
ReduceJSConvertReceiver(Node * node)1393 Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
1394   DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
1395   ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
1396   Node* receiver = NodeProperties::GetValueInput(node, 0);
1397   Type* receiver_type = NodeProperties::GetType(receiver);
1398   Node* context = NodeProperties::GetContextInput(node);
1399   Type* context_type = NodeProperties::GetType(context);
1400   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
1401   Node* effect = NodeProperties::GetEffectInput(node);
1402   Node* control = NodeProperties::GetControlInput(node);
1403   if (!receiver_type->Is(Type::Receiver())) {
1404     if (receiver_type->Is(Type::NullOrUndefined()) ||
1405         mode == ConvertReceiverMode::kNullOrUndefined) {
1406       if (context_type->IsConstant()) {
1407         Handle<JSObject> global_proxy(
1408             Handle<Context>::cast(context_type->AsConstant()->Value())
1409                 ->global_proxy(),
1410             isolate());
1411         receiver = jsgraph()->Constant(global_proxy);
1412       } else {
1413         Node* native_context = effect = graph()->NewNode(
1414             javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1415             context, context, effect);
1416         receiver = effect = graph()->NewNode(
1417             javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1418             native_context, native_context, effect);
1419       }
1420     } else if (!receiver_type->Maybe(Type::NullOrUndefined()) ||
1421                mode == ConvertReceiverMode::kNotNullOrUndefined) {
1422       receiver = effect =
1423           graph()->NewNode(javascript()->ToObject(), receiver, context,
1424                            frame_state, effect, control);
1425     } else {
1426       // Check {receiver} for undefined.
1427       Node* check0 =
1428           graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1429                            receiver, jsgraph()->UndefinedConstant());
1430       Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1431                                        check0, control);
1432       Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1433       Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1434 
1435       // Check {receiver} for null.
1436       Node* check1 =
1437           graph()->NewNode(simplified()->ReferenceEqual(receiver_type),
1438                            receiver, jsgraph()->NullConstant());
1439       Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1440                                        check1, if_false0);
1441       Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1442       Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1443 
1444       // Convert {receiver} using ToObject.
1445       Node* if_convert = if_false1;
1446       Node* econvert = effect;
1447       Node* rconvert;
1448       {
1449         rconvert = econvert =
1450             graph()->NewNode(javascript()->ToObject(), receiver, context,
1451                              frame_state, econvert, if_convert);
1452       }
1453 
1454       // Replace {receiver} with global proxy of {context}.
1455       Node* if_global =
1456           graph()->NewNode(common()->Merge(2), if_true0, if_true1);
1457       Node* eglobal = effect;
1458       Node* rglobal;
1459       {
1460         if (context_type->IsConstant()) {
1461           Handle<JSObject> global_proxy(
1462               Handle<Context>::cast(context_type->AsConstant()->Value())
1463                   ->global_proxy(),
1464               isolate());
1465           rglobal = jsgraph()->Constant(global_proxy);
1466         } else {
1467           Node* native_context = eglobal = graph()->NewNode(
1468               javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
1469               context, context, eglobal);
1470           rglobal = eglobal = graph()->NewNode(
1471               javascript()->LoadContext(0, Context::GLOBAL_PROXY_INDEX, true),
1472               native_context, native_context, eglobal);
1473         }
1474       }
1475 
1476       control = graph()->NewNode(common()->Merge(2), if_convert, if_global);
1477       effect =
1478           graph()->NewNode(common()->EffectPhi(2), econvert, eglobal, control);
1479       receiver =
1480           graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1481                            rconvert, rglobal, control);
1482     }
1483   }
1484   ReplaceWithValue(node, receiver, effect, control);
1485   return Changed(receiver);
1486 }
1487 
1488 
ReduceJSCallConstruct(Node * node)1489 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) {
1490   DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
1491   CallConstructParameters const& p = CallConstructParametersOf(node->op());
1492   DCHECK_LE(2u, p.arity());
1493   int const arity = static_cast<int>(p.arity() - 2);
1494   Node* target = NodeProperties::GetValueInput(node, 0);
1495   Type* target_type = NodeProperties::GetType(target);
1496   Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
1497 
1498   // Check if {target} is a known JSFunction.
1499   if (target_type->IsConstant() &&
1500       target_type->AsConstant()->Value()->IsJSFunction()) {
1501     Handle<JSFunction> function =
1502         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1503     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1504 
1505     // Patch {node} to an indirect call via the {function}s construct stub.
1506     Callable callable(handle(shared->construct_stub(), isolate()),
1507                       ConstructStubDescriptor(isolate()));
1508     node->RemoveInput(arity + 1);
1509     node->InsertInput(graph()->zone(), 0,
1510                       jsgraph()->HeapConstant(callable.code()));
1511     node->InsertInput(graph()->zone(), 2, new_target);
1512     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1513     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1514     node->InsertInput(graph()->zone(), 5, jsgraph()->UndefinedConstant());
1515     NodeProperties::ChangeOp(
1516         node, common()->Call(Linkage::GetStubCallDescriptor(
1517                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1518                   CallDescriptor::kNeedsFrameState)));
1519     return Changed(node);
1520   }
1521 
1522   // Check if {target} is a JSFunction.
1523   if (target_type->Is(Type::Function())) {
1524     // Patch {node} to an indirect call via the ConstructFunction builtin.
1525     Callable callable = CodeFactory::ConstructFunction(isolate());
1526     node->RemoveInput(arity + 1);
1527     node->InsertInput(graph()->zone(), 0,
1528                       jsgraph()->HeapConstant(callable.code()));
1529     node->InsertInput(graph()->zone(), 2, new_target);
1530     node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
1531     node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
1532     NodeProperties::ChangeOp(
1533         node, common()->Call(Linkage::GetStubCallDescriptor(
1534                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1535                   CallDescriptor::kNeedsFrameState)));
1536     return Changed(node);
1537   }
1538 
1539   return NoChange();
1540 }
1541 
1542 
ReduceJSCallFunction(Node * node)1543 Reduction JSTypedLowering::ReduceJSCallFunction(Node* node) {
1544   DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
1545   CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
1546   int const arity = static_cast<int>(p.arity() - 2);
1547   ConvertReceiverMode convert_mode = p.convert_mode();
1548   Node* target = NodeProperties::GetValueInput(node, 0);
1549   Type* target_type = NodeProperties::GetType(target);
1550   Node* receiver = NodeProperties::GetValueInput(node, 1);
1551   Type* receiver_type = NodeProperties::GetType(receiver);
1552   Node* effect = NodeProperties::GetEffectInput(node);
1553   Node* control = NodeProperties::GetControlInput(node);
1554   Node* frame_state = NodeProperties::FindFrameStateBefore(node);
1555 
1556   // Try to infer receiver {convert_mode} from {receiver} type.
1557   if (receiver_type->Is(Type::NullOrUndefined())) {
1558     convert_mode = ConvertReceiverMode::kNullOrUndefined;
1559   } else if (!receiver_type->Maybe(Type::NullOrUndefined())) {
1560     convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
1561   }
1562 
1563   // Check if {target} is a known JSFunction.
1564   if (target_type->IsConstant() &&
1565       target_type->AsConstant()->Value()->IsJSFunction()) {
1566     Handle<JSFunction> function =
1567         Handle<JSFunction>::cast(target_type->AsConstant()->Value());
1568     Handle<SharedFunctionInfo> shared(function->shared(), isolate());
1569 
1570     // Class constructors are callable, but [[Call]] will raise an exception.
1571     // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
1572     if (IsClassConstructor(shared->kind())) return NoChange();
1573 
1574     // Load the context from the {target}.
1575     Node* context = effect = graph()->NewNode(
1576         simplified()->LoadField(AccessBuilder::ForJSFunctionContext()), target,
1577         effect, control);
1578     NodeProperties::ReplaceContextInput(node, context);
1579 
1580     // Check if we need to convert the {receiver}.
1581     if (is_sloppy(shared->language_mode()) && !shared->native() &&
1582         !receiver_type->Is(Type::Receiver())) {
1583       receiver = effect =
1584           graph()->NewNode(javascript()->ConvertReceiver(convert_mode),
1585                            receiver, context, frame_state, effect, control);
1586       NodeProperties::ReplaceValueInput(node, receiver, 1);
1587     }
1588 
1589     // Update the effect dependency for the {node}.
1590     NodeProperties::ReplaceEffectInput(node, effect);
1591 
1592     // Compute flags for the call.
1593     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1594     if (p.tail_call_mode() == TailCallMode::kAllow) {
1595       flags |= CallDescriptor::kSupportsTailCalls;
1596     }
1597 
1598     Node* new_target = jsgraph()->UndefinedConstant();
1599     Node* argument_count = jsgraph()->Int32Constant(arity);
1600     if (shared->internal_formal_parameter_count() == arity ||
1601         shared->internal_formal_parameter_count() ==
1602             SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
1603       // Patch {node} to a direct call.
1604       node->InsertInput(graph()->zone(), arity + 2, new_target);
1605       node->InsertInput(graph()->zone(), arity + 3, argument_count);
1606       NodeProperties::ChangeOp(node,
1607                                common()->Call(Linkage::GetJSCallDescriptor(
1608                                    graph()->zone(), false, 1 + arity, flags)));
1609     } else {
1610       // Patch {node} to an indirect call via the ArgumentsAdaptorTrampoline.
1611       Callable callable = CodeFactory::ArgumentAdaptor(isolate());
1612       node->InsertInput(graph()->zone(), 0,
1613                         jsgraph()->HeapConstant(callable.code()));
1614       node->InsertInput(graph()->zone(), 2, new_target);
1615       node->InsertInput(graph()->zone(), 3, argument_count);
1616       node->InsertInput(
1617           graph()->zone(), 4,
1618           jsgraph()->Int32Constant(shared->internal_formal_parameter_count()));
1619       NodeProperties::ChangeOp(
1620           node, common()->Call(Linkage::GetStubCallDescriptor(
1621                     isolate(), graph()->zone(), callable.descriptor(),
1622                     1 + arity, flags)));
1623     }
1624     return Changed(node);
1625   }
1626 
1627   // Check if {target} is a JSFunction.
1628   if (target_type->Is(Type::Function())) {
1629     // Compute flags for the call.
1630     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
1631     if (p.tail_call_mode() == TailCallMode::kAllow) {
1632       flags |= CallDescriptor::kSupportsTailCalls;
1633     }
1634 
1635     // Patch {node} to an indirect call via the CallFunction builtin.
1636     Callable callable = CodeFactory::CallFunction(isolate(), convert_mode);
1637     node->InsertInput(graph()->zone(), 0,
1638                       jsgraph()->HeapConstant(callable.code()));
1639     node->InsertInput(graph()->zone(), 2, jsgraph()->Int32Constant(arity));
1640     NodeProperties::ChangeOp(
1641         node, common()->Call(Linkage::GetStubCallDescriptor(
1642                   isolate(), graph()->zone(), callable.descriptor(), 1 + arity,
1643                   flags)));
1644     return Changed(node);
1645   }
1646 
1647   // Maybe we did at least learn something about the {receiver}.
1648   if (p.convert_mode() != convert_mode) {
1649     NodeProperties::ChangeOp(
1650         node, javascript()->CallFunction(p.arity(), p.feedback(), convert_mode,
1651                                          p.tail_call_mode()));
1652     return Changed(node);
1653   }
1654 
1655   return NoChange();
1656 }
1657 
1658 
ReduceJSForInDone(Node * node)1659 Reduction JSTypedLowering::ReduceJSForInDone(Node* node) {
1660   DCHECK_EQ(IrOpcode::kJSForInDone, node->opcode());
1661   node->TrimInputCount(2);
1662   NodeProperties::ChangeOp(node, machine()->Word32Equal());
1663   return Changed(node);
1664 }
1665 
1666 
ReduceJSForInNext(Node * node)1667 Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
1668   DCHECK_EQ(IrOpcode::kJSForInNext, node->opcode());
1669   Node* receiver = NodeProperties::GetValueInput(node, 0);
1670   Node* cache_array = NodeProperties::GetValueInput(node, 1);
1671   Node* cache_type = NodeProperties::GetValueInput(node, 2);
1672   Node* index = NodeProperties::GetValueInput(node, 3);
1673   Node* context = NodeProperties::GetContextInput(node);
1674   Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
1675   Node* effect = NodeProperties::GetEffectInput(node);
1676   Node* control = NodeProperties::GetControlInput(node);
1677 
1678   // Load the next {key} from the {cache_array}.
1679   Node* key = effect = graph()->NewNode(
1680       simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
1681       cache_array, index, effect, control);
1682 
1683   // Load the map of the {receiver}.
1684   Node* receiver_map = effect =
1685       graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
1686                        receiver, effect, control);
1687 
1688   // Check if the expected map still matches that of the {receiver}.
1689   Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()),
1690                                   receiver_map, cache_type);
1691   Node* branch0 =
1692       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
1693 
1694   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1695   Node* etrue0;
1696   Node* vtrue0;
1697   {
1698     // Don't need filtering since expected map still matches that of the
1699     // {receiver}.
1700     etrue0 = effect;
1701     vtrue0 = key;
1702   }
1703 
1704   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1705   Node* efalse0;
1706   Node* vfalse0;
1707   {
1708     // Filter the {key} to check if it's still a valid property of the
1709     // {receiver} (does the ToName conversion implicitly).
1710     vfalse0 = efalse0 = graph()->NewNode(
1711         javascript()->CallRuntime(Runtime::kForInFilter), receiver, key,
1712         context, frame_state, effect, if_false0);
1713     if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
1714   }
1715 
1716   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1717   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
1718   ReplaceWithValue(node, node, effect, control);
1719   node->ReplaceInput(0, vtrue0);
1720   node->ReplaceInput(1, vfalse0);
1721   node->ReplaceInput(2, control);
1722   node->TrimInputCount(3);
1723   NodeProperties::ChangeOp(node,
1724                            common()->Phi(MachineRepresentation::kTagged, 2));
1725   return Changed(node);
1726 }
1727 
1728 
ReduceJSForInStep(Node * node)1729 Reduction JSTypedLowering::ReduceJSForInStep(Node* node) {
1730   DCHECK_EQ(IrOpcode::kJSForInStep, node->opcode());
1731   node->ReplaceInput(1, jsgraph()->Int32Constant(1));
1732   NodeProperties::ChangeOp(node, machine()->Int32Add());
1733   return Changed(node);
1734 }
1735 
ReduceJSGeneratorStore(Node * node)1736 Reduction JSTypedLowering::ReduceJSGeneratorStore(Node* node) {
1737   DCHECK_EQ(IrOpcode::kJSGeneratorStore, node->opcode());
1738   Node* generator = NodeProperties::GetValueInput(node, 0);
1739   Node* continuation = NodeProperties::GetValueInput(node, 1);
1740   Node* offset = NodeProperties::GetValueInput(node, 2);
1741   Node* context = NodeProperties::GetContextInput(node);
1742   Node* effect = NodeProperties::GetEffectInput(node);
1743   Node* control = NodeProperties::GetControlInput(node);
1744   int register_count = OpParameter<int>(node);
1745 
1746   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
1747   FieldAccess context_field = AccessBuilder::ForJSGeneratorObjectContext();
1748   FieldAccess continuation_field =
1749       AccessBuilder::ForJSGeneratorObjectContinuation();
1750   FieldAccess input_or_debug_pos_field =
1751       AccessBuilder::ForJSGeneratorObjectInputOrDebugPos();
1752 
1753   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
1754                                           generator, effect, control);
1755 
1756   for (int i = 0; i < register_count; ++i) {
1757     Node* value = NodeProperties::GetValueInput(node, 3 + i);
1758     effect = graph()->NewNode(
1759         simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), array,
1760         value, effect, control);
1761   }
1762 
1763   effect = graph()->NewNode(simplified()->StoreField(context_field), generator,
1764                             context, effect, control);
1765   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
1766                             generator, continuation, effect, control);
1767   effect = graph()->NewNode(simplified()->StoreField(input_or_debug_pos_field),
1768                             generator, offset, effect, control);
1769 
1770   ReplaceWithValue(node, effect, effect, control);
1771   return Changed(effect);
1772 }
1773 
ReduceJSGeneratorRestoreContinuation(Node * node)1774 Reduction JSTypedLowering::ReduceJSGeneratorRestoreContinuation(Node* node) {
1775   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreContinuation, node->opcode());
1776   Node* generator = NodeProperties::GetValueInput(node, 0);
1777   Node* effect = NodeProperties::GetEffectInput(node);
1778   Node* control = NodeProperties::GetControlInput(node);
1779 
1780   FieldAccess continuation_field =
1781       AccessBuilder::ForJSGeneratorObjectContinuation();
1782 
1783   Node* continuation = effect = graph()->NewNode(
1784       simplified()->LoadField(continuation_field), generator, effect, control);
1785   Node* executing = jsgraph()->Constant(JSGeneratorObject::kGeneratorExecuting);
1786   effect = graph()->NewNode(simplified()->StoreField(continuation_field),
1787                             generator, executing, effect, control);
1788 
1789   ReplaceWithValue(node, continuation, effect, control);
1790   return Changed(continuation);
1791 }
1792 
ReduceJSGeneratorRestoreRegister(Node * node)1793 Reduction JSTypedLowering::ReduceJSGeneratorRestoreRegister(Node* node) {
1794   DCHECK_EQ(IrOpcode::kJSGeneratorRestoreRegister, node->opcode());
1795   Node* generator = NodeProperties::GetValueInput(node, 0);
1796   Node* effect = NodeProperties::GetEffectInput(node);
1797   Node* control = NodeProperties::GetControlInput(node);
1798   int index = OpParameter<int>(node);
1799 
1800   FieldAccess array_field = AccessBuilder::ForJSGeneratorObjectOperandStack();
1801   FieldAccess element_field = AccessBuilder::ForFixedArraySlot(index);
1802 
1803   Node* array = effect = graph()->NewNode(simplified()->LoadField(array_field),
1804                                           generator, effect, control);
1805   Node* element = effect = graph()->NewNode(
1806       simplified()->LoadField(element_field), array, effect, control);
1807   Node* stale = jsgraph()->StaleRegisterConstant();
1808   effect = graph()->NewNode(simplified()->StoreField(element_field), array,
1809                             stale, effect, control);
1810 
1811   ReplaceWithValue(node, element, effect, control);
1812   return Changed(element);
1813 }
1814 
ReduceSelect(Node * node)1815 Reduction JSTypedLowering::ReduceSelect(Node* node) {
1816   DCHECK_EQ(IrOpcode::kSelect, node->opcode());
1817   Node* const condition = NodeProperties::GetValueInput(node, 0);
1818   Type* const condition_type = NodeProperties::GetType(condition);
1819   Node* const vtrue = NodeProperties::GetValueInput(node, 1);
1820   Type* const vtrue_type = NodeProperties::GetType(vtrue);
1821   Node* const vfalse = NodeProperties::GetValueInput(node, 2);
1822   Type* const vfalse_type = NodeProperties::GetType(vfalse);
1823   if (condition_type->Is(true_type_)) {
1824     // Select(condition:true, vtrue, vfalse) => vtrue
1825     return Replace(vtrue);
1826   }
1827   if (condition_type->Is(false_type_)) {
1828     // Select(condition:false, vtrue, vfalse) => vfalse
1829     return Replace(vfalse);
1830   }
1831   if (vtrue_type->Is(true_type_) && vfalse_type->Is(false_type_)) {
1832     // Select(condition, vtrue:true, vfalse:false) => condition
1833     return Replace(condition);
1834   }
1835   if (vtrue_type->Is(false_type_) && vfalse_type->Is(true_type_)) {
1836     // Select(condition, vtrue:false, vfalse:true) => BooleanNot(condition)
1837     node->TrimInputCount(1);
1838     NodeProperties::ChangeOp(node, simplified()->BooleanNot());
1839     return Changed(node);
1840   }
1841   return NoChange();
1842 }
1843 
1844 
Reduce(Node * node)1845 Reduction JSTypedLowering::Reduce(Node* node) {
1846   // Check if the output type is a singleton.  In that case we already know the
1847   // result value and can simply replace the node if it's eliminable.
1848   if (!NodeProperties::IsConstant(node) && NodeProperties::IsTyped(node) &&
1849       node->op()->HasProperty(Operator::kEliminatable)) {
1850     // We can only constant-fold nodes here, that are known to not cause any
1851     // side-effect, may it be a JavaScript observable side-effect or a possible
1852     // eager deoptimization exit (i.e. {node} has an operator that doesn't have
1853     // the Operator::kNoDeopt property).
1854     Type* upper = NodeProperties::GetType(node);
1855     if (upper->IsInhabited()) {
1856       if (upper->IsConstant()) {
1857         Node* replacement = jsgraph()->Constant(upper->AsConstant()->Value());
1858         ReplaceWithValue(node, replacement);
1859         return Changed(replacement);
1860       } else if (upper->Is(Type::MinusZero())) {
1861         Node* replacement = jsgraph()->Constant(factory()->minus_zero_value());
1862         ReplaceWithValue(node, replacement);
1863         return Changed(replacement);
1864       } else if (upper->Is(Type::NaN())) {
1865         Node* replacement = jsgraph()->NaNConstant();
1866         ReplaceWithValue(node, replacement);
1867         return Changed(replacement);
1868       } else if (upper->Is(Type::Null())) {
1869         Node* replacement = jsgraph()->NullConstant();
1870         ReplaceWithValue(node, replacement);
1871         return Changed(replacement);
1872       } else if (upper->Is(Type::PlainNumber()) &&
1873                  upper->Min() == upper->Max()) {
1874         Node* replacement = jsgraph()->Constant(upper->Min());
1875         ReplaceWithValue(node, replacement);
1876         return Changed(replacement);
1877       } else if (upper->Is(Type::Undefined())) {
1878         Node* replacement = jsgraph()->UndefinedConstant();
1879         ReplaceWithValue(node, replacement);
1880         return Changed(replacement);
1881       }
1882     }
1883   }
1884   switch (node->opcode()) {
1885     case IrOpcode::kJSEqual:
1886       return ReduceJSEqual(node, false);
1887     case IrOpcode::kJSNotEqual:
1888       return ReduceJSEqual(node, true);
1889     case IrOpcode::kJSStrictEqual:
1890       return ReduceJSStrictEqual(node, false);
1891     case IrOpcode::kJSStrictNotEqual:
1892       return ReduceJSStrictEqual(node, true);
1893     case IrOpcode::kJSLessThan:         // fall through
1894     case IrOpcode::kJSGreaterThan:      // fall through
1895     case IrOpcode::kJSLessThanOrEqual:  // fall through
1896     case IrOpcode::kJSGreaterThanOrEqual:
1897       return ReduceJSComparison(node);
1898     case IrOpcode::kJSBitwiseOr:
1899       return ReduceInt32Binop(node, simplified()->NumberBitwiseOr());
1900     case IrOpcode::kJSBitwiseXor:
1901       return ReduceInt32Binop(node, simplified()->NumberBitwiseXor());
1902     case IrOpcode::kJSBitwiseAnd:
1903       return ReduceInt32Binop(node, simplified()->NumberBitwiseAnd());
1904     case IrOpcode::kJSShiftLeft:
1905       return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftLeft());
1906     case IrOpcode::kJSShiftRight:
1907       return ReduceUI32Shift(node, kSigned, simplified()->NumberShiftRight());
1908     case IrOpcode::kJSShiftRightLogical:
1909       return ReduceUI32Shift(node, kUnsigned,
1910                              simplified()->NumberShiftRightLogical());
1911     case IrOpcode::kJSAdd:
1912       return ReduceJSAdd(node);
1913     case IrOpcode::kJSSubtract:
1914       return ReduceJSSubtract(node);
1915     case IrOpcode::kJSMultiply:
1916       return ReduceJSMultiply(node);
1917     case IrOpcode::kJSDivide:
1918       return ReduceJSDivide(node);
1919     case IrOpcode::kJSModulus:
1920       return ReduceJSModulus(node);
1921     case IrOpcode::kJSToBoolean:
1922       return ReduceJSToBoolean(node);
1923     case IrOpcode::kJSToInteger:
1924       return ReduceJSToInteger(node);
1925     case IrOpcode::kJSToLength:
1926       return ReduceJSToLength(node);
1927     case IrOpcode::kJSToNumber:
1928       return ReduceJSToNumber(node);
1929     case IrOpcode::kJSToString:
1930       return ReduceJSToString(node);
1931     case IrOpcode::kJSToObject:
1932       return ReduceJSToObject(node);
1933     case IrOpcode::kJSLoadNamed:
1934       return ReduceJSLoadNamed(node);
1935     case IrOpcode::kJSLoadProperty:
1936       return ReduceJSLoadProperty(node);
1937     case IrOpcode::kJSStoreProperty:
1938       return ReduceJSStoreProperty(node);
1939     case IrOpcode::kJSInstanceOf:
1940       return ReduceJSInstanceOf(node);
1941     case IrOpcode::kJSLoadContext:
1942       return ReduceJSLoadContext(node);
1943     case IrOpcode::kJSStoreContext:
1944       return ReduceJSStoreContext(node);
1945     case IrOpcode::kJSConvertReceiver:
1946       return ReduceJSConvertReceiver(node);
1947     case IrOpcode::kJSCallConstruct:
1948       return ReduceJSCallConstruct(node);
1949     case IrOpcode::kJSCallFunction:
1950       return ReduceJSCallFunction(node);
1951     case IrOpcode::kJSForInDone:
1952       return ReduceJSForInDone(node);
1953     case IrOpcode::kJSForInNext:
1954       return ReduceJSForInNext(node);
1955     case IrOpcode::kJSForInStep:
1956       return ReduceJSForInStep(node);
1957     case IrOpcode::kJSGeneratorStore:
1958       return ReduceJSGeneratorStore(node);
1959     case IrOpcode::kJSGeneratorRestoreContinuation:
1960       return ReduceJSGeneratorRestoreContinuation(node);
1961     case IrOpcode::kJSGeneratorRestoreRegister:
1962       return ReduceJSGeneratorRestoreRegister(node);
1963     case IrOpcode::kSelect:
1964       return ReduceSelect(node);
1965     default:
1966       break;
1967   }
1968   return NoChange();
1969 }
1970 
1971 
Word32Shl(Node * const lhs,int32_t const rhs)1972 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) {
1973   if (rhs == 0) return lhs;
1974   return graph()->NewNode(machine()->Word32Shl(), lhs,
1975                           jsgraph()->Int32Constant(rhs));
1976 }
1977 
EmptyFrameState()1978 Node* JSTypedLowering::EmptyFrameState() {
1979   return graph()->NewNode(
1980       common()->FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(),
1981                            nullptr),
1982       jsgraph()->EmptyStateValues(), jsgraph()->EmptyStateValues(),
1983       jsgraph()->EmptyStateValues(), jsgraph()->NoContextConstant(),
1984       jsgraph()->UndefinedConstant(), graph()->start());
1985 }
1986 
factory() const1987 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); }
1988 
1989 
graph() const1990 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); }
1991 
1992 
isolate() const1993 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); }
1994 
1995 
javascript() const1996 JSOperatorBuilder* JSTypedLowering::javascript() const {
1997   return jsgraph()->javascript();
1998 }
1999 
2000 
common() const2001 CommonOperatorBuilder* JSTypedLowering::common() const {
2002   return jsgraph()->common();
2003 }
2004 
2005 
simplified() const2006 SimplifiedOperatorBuilder* JSTypedLowering::simplified() const {
2007   return jsgraph()->simplified();
2008 }
2009 
2010 
machine() const2011 MachineOperatorBuilder* JSTypedLowering::machine() const {
2012   return jsgraph()->machine();
2013 }
2014 
2015 
dependencies() const2016 CompilationDependencies* JSTypedLowering::dependencies() const {
2017   return dependencies_;
2018 }
2019 
2020 }  // namespace compiler
2021 }  // namespace internal
2022 }  // namespace v8
2023