32 JSTypedLowering::~JSTypedLowering() {}
35 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
73 jsgraph()->Int32Constant(0x1F)));
79 node_->ReplaceInput(0, r);
80 node_->ReplaceInput(1, l);
104 node_->ReplaceUses(value);
106 value->ReplaceInput(0,
node_);
148 Reduction reduced =
lowering_->ReduceJSToStringInput(node);
149 if (reduced.Changed())
return reduced.replacement();
158 Reduction reduced =
lowering_->ReduceJSToNumberInput(node);
159 if (reduced.Changed())
return reduced.replacement();
168 switch (node->opcode()) {
169 case IrOpcode::kFloat64Add:
170 case IrOpcode::kNumberAdd: {
173 node->set_op(
lowering_->machine()->Int32Add());
179 case IrOpcode::kFloat64Sub:
180 case IrOpcode::kNumberSubtract: {
183 node->set_op(
lowering_->machine()->Int32Sub());
195 Type* type = is_signed ? Type::Signed32() : Type::Unsigned32();
196 if (node->OwnedBy(
node_)) {
210 if (input_type->
Is(type))
return node;
224 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
225 JSBinopReduction r(
this, node);
226 if (r.BothInputsAre(Type::Number())) {
228 return r.ChangeToPureOperator(simplified()->NumberAdd());
230 Type* maybe_string =
Type::Union(Type::String(), Type::Receiver(), zone());
231 if (r.NeitherInputCanBe(maybe_string)) {
233 r.ConvertInputsToNumber();
234 return r.ChangeToPureOperator(simplified()->NumberAdd());
241 if (r.OneInputIs(Type::String())) {
245 r.ConvertInputsToString();
246 return r.ChangeToPureOperator(simplified()->StringAdd());
253 Reduction JSTypedLowering::ReduceNumberBinop(Node* node,
254 const Operator* numberOp) {
255 JSBinopReduction r(
this, node);
256 if (r.OneInputIs(Type::Primitive())) {
260 r.ConvertInputsToNumber();
261 return r.ChangeToPureOperator(numberOp);
268 Reduction JSTypedLowering::ReduceI32Binop(Node* node,
bool left_signed,
270 const Operator* intOp) {
271 JSBinopReduction r(
this, node);
276 r.ConvertInputsToInt32(left_signed, right_signed);
277 return r.ChangeToPureOperator(intOp);
281 Reduction JSTypedLowering::ReduceI32Shift(Node* node,
bool left_signed,
282 const Operator* shift_op) {
283 JSBinopReduction r(
this, node);
284 r.ConvertInputsForShift(left_signed);
285 return r.ChangeToPureOperator(shift_op);
289 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
290 JSBinopReduction r(
this, node);
291 if (r.BothInputsAre(Type::String())) {
293 const Operator* stringOp;
294 switch (node->opcode()) {
295 case IrOpcode::kJSLessThan:
296 stringOp = simplified()->StringLessThan();
298 case IrOpcode::kJSGreaterThan:
299 stringOp = simplified()->StringLessThan();
302 case IrOpcode::kJSLessThanOrEqual:
303 stringOp = simplified()->StringLessThanOrEqual();
305 case IrOpcode::kJSGreaterThanOrEqual:
306 stringOp = simplified()->StringLessThanOrEqual();
312 return r.ChangeToPureOperator(stringOp);
314 Type* maybe_string =
Type::Union(Type::String(), Type::Receiver(), zone());
315 if (r.OneInputCannotBe(maybe_string)) {
317 const Operator* less_than;
318 const Operator* less_than_or_equal;
319 if (r.BothInputsAre(Type::Unsigned32())) {
320 less_than = machine()->Uint32LessThan();
321 less_than_or_equal = machine()->Uint32LessThanOrEqual();
322 }
else if (r.BothInputsAre(Type::Signed32())) {
323 less_than = machine()->Int32LessThan();
324 less_than_or_equal = machine()->Int32LessThanOrEqual();
327 r.ConvertInputsToNumber();
328 less_than = simplified()->NumberLessThan();
329 less_than_or_equal = simplified()->NumberLessThanOrEqual();
331 const Operator* comparison;
332 switch (node->opcode()) {
333 case IrOpcode::kJSLessThan:
334 comparison = less_than;
336 case IrOpcode::kJSGreaterThan:
337 comparison = less_than;
340 case IrOpcode::kJSLessThanOrEqual:
341 comparison = less_than_or_equal;
343 case IrOpcode::kJSGreaterThanOrEqual:
344 comparison = less_than_or_equal;
350 return r.ChangeToPureOperator(comparison);
357 Reduction JSTypedLowering::ReduceJSEqual(Node* node,
bool invert) {
358 JSBinopReduction r(
this, node);
360 if (r.BothInputsAre(Type::Number())) {
361 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
363 if (r.BothInputsAre(Type::String())) {
364 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
366 if (r.BothInputsAre(Type::Receiver())) {
367 return r.ChangeToPureOperator(
368 simplified()->ReferenceEqual(Type::Receiver()), invert);
377 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node,
bool invert) {
378 JSBinopReduction r(
this, node);
379 if (r.left() == r.right()) {
381 if (!r.left_type()->Maybe(Type::NaN())) {
382 return ReplaceEagerly(node, invert ? jsgraph()->FalseConstant()
383 : jsgraph()->TrueConstant());
386 if (!r.left_type()->Maybe(r.right_type())) {
389 if (r.OneInputCannotBe(Type::String())) {
390 return ReplaceEagerly(node, invert ? jsgraph()->TrueConstant()
391 : jsgraph()->FalseConstant());
395 return r.ChangeToPureOperator(
399 return r.ChangeToPureOperator(simplified()->ReferenceEqual(
Type::Null()),
402 if (r.OneInputIs(Type::Boolean())) {
403 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
407 return r.ChangeToPureOperator(simplified()->ReferenceEqual(
Type::Object()),
410 if (r.OneInputIs(Type::Receiver())) {
411 return r.ChangeToPureOperator(
412 simplified()->ReferenceEqual(Type::Receiver()), invert);
414 if (r.BothInputsAre(Type::String())) {
415 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
417 if (r.BothInputsAre(Type::Number())) {
418 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
425 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
426 if (input->opcode() == IrOpcode::kJSToNumber) {
428 Reduction result = ReduceJSToNumberInput(input->InputAt(0));
429 if (result.Changed()) {
433 return Changed(input);
436 if (input_type->Is(Type::Number())) {
438 return Changed(input);
442 return ReplaceWith(jsgraph()->NaNConstant());
446 return ReplaceWith(jsgraph()->ZeroConstant());
448 if (input_type->Is(Type::Boolean())) {
451 graph()->NewNode(simplified()->BooleanToNumber(), input));
458 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
459 if (input->opcode() == IrOpcode::kJSToString) {
461 Reduction result = ReduceJSToStringInput(input->InputAt(0));
462 if (result.Changed()) {
466 return Changed(input);
469 if (input_type->Is(Type::String())) {
470 return Changed(input);
473 return ReplaceWith(jsgraph()->HeapConstant(
474 graph()->zone()->isolate()->factory()->undefined_string()));
477 return ReplaceWith(jsgraph()->HeapConstant(
478 graph()->zone()->isolate()->factory()->null_string()));
486 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
487 if (input->opcode() == IrOpcode::kJSToBoolean) {
489 Reduction result = ReduceJSToBooleanInput(input->InputAt(0));
490 if (result.Changed()) {
494 return Changed(input);
497 if (input_type->Is(Type::Boolean())) {
498 return Changed(input);
502 return ReplaceWith(jsgraph()->FalseConstant());
506 return ReplaceWith(jsgraph()->FalseConstant());
508 if (input_type->Is(Type::DetectableReceiver())) {
510 return ReplaceWith(jsgraph()->TrueConstant());
512 if (input_type->Is(Type::Undetectable())) {
514 return ReplaceWith(jsgraph()->FalseConstant());
516 if (input_type->Is(Type::OrderedNumber())) {
518 Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
519 jsgraph()->ZeroConstant());
520 Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
521 return ReplaceWith(inv);
528 Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
537 if (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
538 base_type->AsConstant()->Value()->IsJSTypedArray()) {
540 JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
541 ElementsKind elements_kind = array->map()->elements_kind();
544 CHECK(array->length()->ToUint32(&length));
545 ElementAccess element_access;
546 Node* elements = graph()->NewNode(
547 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
550 elements = graph()->NewNode(
551 simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
553 element_access = AccessBuilder::ForTypedArrayElement(type,
true);
556 element_access = AccessBuilder::ForTypedArrayElement(type,
false);
559 graph()->NewNode(simplified()->LoadElement(element_access), elements,
560 key, jsgraph()->Uint32Constant(length),
562 return ReplaceEagerly(node, value);
568 Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
577 if (key_type->Is(Type::Integral32()) && base_type->IsConstant() &&
578 base_type->AsConstant()->Value()->IsJSTypedArray()) {
580 JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
581 ElementsKind elements_kind = array->map()->elements_kind();
584 CHECK(array->length()->ToUint32(&length));
585 ElementAccess element_access;
586 Node* elements = graph()->NewNode(
587 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
590 elements = graph()->NewNode(
591 simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
593 element_access = AccessBuilder::ForTypedArrayElement(type,
true);
596 element_access = AccessBuilder::ForTypedArrayElement(type,
false);
599 Node* check = graph()->NewNode(machine()->Uint32LessThan(), key,
600 jsgraph()->Uint32Constant(length));
601 Node* branch = graph()->NewNode(common()->Branch(), check,
604 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
607 graph()->NewNode(simplified()->StoreElement(element_access), elements,
608 key, jsgraph()->Uint32Constant(length), value,
611 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
613 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
614 Node* phi = graph()->NewNode(common()->EffectPhi(2), store,
617 return ReplaceWith(phi);
624 if (reduction.Changed()) {
632 Reduction JSTypedLowering::Reduce(Node* node) {
633 switch (node->opcode()) {
634 case IrOpcode::kJSEqual:
635 return ReduceJSEqual(node,
false);
636 case IrOpcode::kJSNotEqual:
637 return ReduceJSEqual(node,
true);
638 case IrOpcode::kJSStrictEqual:
639 return ReduceJSStrictEqual(node,
false);
640 case IrOpcode::kJSStrictNotEqual:
641 return ReduceJSStrictEqual(node,
true);
642 case IrOpcode::kJSLessThan:
643 case IrOpcode::kJSGreaterThan:
644 case IrOpcode::kJSLessThanOrEqual:
645 case IrOpcode::kJSGreaterThanOrEqual:
646 return ReduceJSComparison(node);
647 case IrOpcode::kJSBitwiseOr:
648 return ReduceI32Binop(node,
true,
true, machine()->Word32Or());
649 case IrOpcode::kJSBitwiseXor:
650 return ReduceI32Binop(node,
true,
true, machine()->Word32Xor());
651 case IrOpcode::kJSBitwiseAnd:
652 return ReduceI32Binop(node,
true,
true, machine()->Word32And());
653 case IrOpcode::kJSShiftLeft:
654 return ReduceI32Shift(node,
true, machine()->Word32Shl());
655 case IrOpcode::kJSShiftRight:
656 return ReduceI32Shift(node,
true, machine()->Word32Sar());
657 case IrOpcode::kJSShiftRightLogical:
658 return ReduceI32Shift(node,
false, machine()->Word32Shr());
659 case IrOpcode::kJSAdd:
660 return ReduceJSAdd(node);
661 case IrOpcode::kJSSubtract:
662 return ReduceNumberBinop(node, simplified()->NumberSubtract());
663 case IrOpcode::kJSMultiply:
664 return ReduceNumberBinop(node, simplified()->NumberMultiply());
665 case IrOpcode::kJSDivide:
666 return ReduceNumberBinop(node, simplified()->NumberDivide());
667 case IrOpcode::kJSModulus:
668 return ReduceNumberBinop(node, simplified()->NumberModulus());
669 case IrOpcode::kJSUnaryNot: {
670 Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
672 if (result.Changed()) {
675 graph()->NewNode(simplified()->BooleanNot(), result.replacement());
677 return Changed(value);
680 value = graph()->NewNode(simplified()->BooleanNot(), node);
681 node->set_op(javascript()->ToBoolean());
684 value->ReplaceInput(0, node);
685 return Changed(node);
688 case IrOpcode::kJSToBoolean:
690 ReduceJSToBooleanInput(node->InputAt(0)));
691 case IrOpcode::kJSToNumber:
693 ReduceJSToNumberInput(node->InputAt(0)));
694 case IrOpcode::kJSToString:
696 ReduceJSToStringInput(node->InputAt(0)));
697 case IrOpcode::kJSLoadProperty:
698 return ReduceJSLoadProperty(node);
699 case IrOpcode::kJSStoreProperty:
700 return ReduceJSStoreProperty(node);
701 case IrOpcode::kJSCallFunction:
702 return JSBuiltinReducer(jsgraph()).Reduce(node);
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
bool Maybe(TypeImpl *that)
Node * NewNode(const Operator *op, int input_count, Node **inputs)
void ConvertInputsToNumber()
JSOperatorBuilder * javascript()
bool OneInputCannotBe(Type *t)
JSTypedLowering * lowering_
void update_effect(Node *effect)
SimplifiedOperatorBuilder * simplified()
void ConvertInputsForShift(bool left_signed)
Node * ConvertToNumber(Node *node)
Reduction ChangeToPureOperator(const Operator *op, bool invert=false)
bool NeitherInputCanBe(Type *t)
Node * ConvertToI32(bool is_signed, Node *node)
void ConvertInputsToString()
MachineOperatorBuilder * machine()
JSBinopReduction(JSTypedLowering *lowering, Node *node)
Node * ConvertToString(Node *node)
void ConvertInputsToInt32(bool left_signed, bool right_signed)
bool TryNarrowingToI32(Type *type, Node *node)
bool BothInputsAre(Type *t)
static void ReplaceWithValue(Node *node, Node *value, Node *effect=NULL)
static void ReplaceEffectInput(Node *node, Node *effect, int index=0)
static void RemoveNonValueInputs(Node *node)
static Node * GetContextInput(Node *node)
static Node * GetValueInput(Node *node, int index)
static Bounds GetBounds(Node *node)
static void SetBounds(Node *node, Bounds bounds)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetControlInput(Node *node, int index=0)
static int GetEffectInputCount(const Operator *op)
static int GetValueInputCount(const Operator *op)
static bool HasContextInput(const Operator *op)
static int GetControlInputCount(const Operator *op)
static Reduction NoChange()
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
static Reduction ReplaceWithReduction(Node *node, Reduction reduction)
static void RelaxEffects(Node *node)
bool IsExternalArrayElementsKind(ElementsKind kind)
TypeImpl< ZoneTypeConfig > Type
int ToNumber(Register reg)
kSerializedDataOffset Object
BoundsImpl< ZoneTypeConfig > Bounds
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
Debugger support for the V8 JavaScript engine.
Handle< Primitive > Null(Isolate *isolate)
Handle< Primitive > Undefined(Isolate *isolate)