20 Type* number = Type::Number();
21 Type* signed32 = Type::Signed32();
22 Type* unsigned32 = Type::Unsigned32();
23 Type* integral32 = Type::Integral32();
36 Type::UnsignedSmall(), Type::OtherNumber(),
zone),
zone);
39 #define NATIVE_TYPE(sem, rep) \
40 Type::Intersect(Type::sem(zone), Type::rep(zone), zone)
81 switch (node->opcode()) {
82 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
87 #define DECLARE_CASE(x) case IrOpcode::k##x:
100 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
103 #undef DECLARE_METHOD
140 for (
int i = 0;
i < arity; ++
i) {
168 return previous.
Narrows(bounds)
194 return bounds.
Narrows(previous)
212 Widen(graph, *
i, context);
243 Bounds Typer::Visitor::TypeStart(Node* node) {
250 Bounds Typer::Visitor::TypeParameter(Node* node) {
255 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
261 Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
264 Type::Of(
static_cast<double>(OpParameter<int64_t>(node)),
zone()));
268 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
274 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
280 Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
286 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
291 Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
296 Bounds Typer::Visitor::TypePhi(Node* node) {
298 Bounds bounds = OperandType(node, 0);
299 for (
int i = 1;
i < arity; ++
i) {
306 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
312 Bounds Typer::Visitor::TypeControlEffect(Node* node) {
318 Bounds Typer::Visitor::TypeValueEffect(Node* node) {
324 Bounds Typer::Visitor::TypeFinish(Node* node) {
325 return OperandType(node, 0);
329 Bounds Typer::Visitor::TypeFrameState(Node* node) {
335 Bounds Typer::Visitor::TypeStateValues(Node* node) {
340 Bounds Typer::Visitor::TypeCall(Node* node) {
345 Bounds Typer::Visitor::TypeProjection(Node* node) {
353 #define DEFINE_METHOD(x) \
354 Bounds Typer::Visitor::Type##x(Node* node) { \
355 return Bounds(Type::Boolean(zone())); \
363 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) {
364 Bounds left = OperandType(node, 0);
365 Bounds right = OperandType(node, 1);
367 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(
zone());
369 return Bounds(lower, upper);
373 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) {
374 Bounds left = OperandType(node, 0);
375 Bounds right = OperandType(node, 1);
377 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(
zone());
379 return Bounds(lower, upper);
383 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) {
388 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) {
393 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) {
398 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) {
399 return Bounds(Type::UnsignedSmall(
zone()), Type::Unsigned32(
zone()));
405 Bounds Typer::Visitor::TypeJSAdd(Node* node) {
406 Bounds left = OperandType(node, 0);
407 Bounds right = OperandType(node, 1);
411 left.lower->
Is(
Type::Number()) && right.lower->
Is(
Type::Number()) ?
413 left.lower->
Is(
Type::String()) || right.lower->
Is(
Type::String()) ?
418 left.upper->
Is(
Type::Number()) && right.upper->
Is(
Type::Number()) ?
420 left.upper->
Is(
Type::String()) || right.upper->
Is(
Type::String()) ?
422 return Bounds(lower, upper);
426 Bounds Typer::Visitor::TypeJSSubtract(Node* node) {
431 Bounds Typer::Visitor::TypeJSMultiply(Node* node) {
436 Bounds Typer::Visitor::TypeJSDivide(Node* node) {
441 Bounds Typer::Visitor::TypeJSModulus(Node* node) {
448 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
453 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
454 return Bounds(Type::InternalizedString(
zone()));
460 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
465 Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
470 Bounds Typer::Visitor::TypeJSToString(Node* node) {
475 Bounds Typer::Visitor::TypeJSToName(Node* node) {
480 Bounds Typer::Visitor::TypeJSToObject(Node* node) {
487 Bounds Typer::Visitor::TypeJSCreate(Node* node) {
492 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
493 Bounds object = OperandType(node, 0);
497 if (
object.lower->IsArray() &&
name.lower->Is(Type::Integral32())) {
501 if (
object.upper->IsArray() &&
name.upper->Is(Type::Integral32())) {
509 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
514 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
520 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
526 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
531 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
536 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
543 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
544 Bounds outer = OperandType(node, 0);
545 DCHECK(outer.upper->Maybe(Type::Internal()));
549 ContextAccess access = OpParameter<ContextAccess>(node);
550 Type* context_type = outer.upper;
551 MaybeHandle<Context> context;
552 if (context_type->IsConstant()) {
560 for (
int i = access.depth();
i > 0; --
i) {
561 if (context_type->IsContext()) {
562 context_type = context_type->AsContext()->Outer();
563 if (context_type->IsConstant()) {
566 }
else if (!context.is_null()) {
567 context =
handle(context.ToHandleChecked()->previous(),
isolate());
570 if (context.is_null()) {
573 Handle<Object> value =
574 handle(context.ToHandleChecked()->get(access.index()),
isolate());
575 Type* lower = TypeConstant(value);
581 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
587 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
588 Type* outer = ContextType(node);
593 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
594 Type* outer = ContextType(node);
599 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
600 Type* outer = ContextType(node);
605 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
606 Type* outer = ContextType(node);
611 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
613 Type* outer = ContextType(node);
618 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) {
619 Type* outer = ContextType(node);
626 Bounds Typer::Visitor::TypeJSYield(Node* node) {
631 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
636 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
637 Bounds fun = OperandType(node, 0);
641 ? fun.upper->AsFunction()->Result() : Type::Any(
zone());
642 return Bounds(lower, upper);
646 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
651 Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
658 Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
663 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
668 Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
673 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
678 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
683 Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
688 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
693 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
698 Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
703 Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
708 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
709 Bounds arg = OperandType(node, 0);
713 return Bounds(lower, upper);
717 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
718 Bounds arg = OperandType(node, 0);
722 return Bounds(lower, upper);
726 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
731 Bounds Typer::Visitor::TypeStringEqual(Node* node) {
736 Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
741 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
746 Bounds Typer::Visitor::TypeStringAdd(Node* node) {
751 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
753 return Bounds(Type::Integral32());
757 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
758 return Bounds(Type::Integral32());
762 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
764 return Bounds(Type::Number());
768 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
770 return Bounds(Type::Integral32());
774 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
776 return Bounds(Type::Unsigned32());
780 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
782 return Bounds(Type::Number());
786 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
788 return Bounds(Type::Boolean());
792 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
794 return Bounds(Type::Boolean());
798 Bounds Typer::Visitor::TypeLoadField(Node* node) {
803 Bounds Typer::Visitor::TypeLoadElement(Node* node) {
808 Bounds Typer::Visitor::TypeStoreField(Node* node) {
814 Bounds Typer::Visitor::TypeStoreElement(Node* node) {
823 #define DEFINE_METHOD(x) \
824 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); }
832 if (value->IsJSFunction() && JSFunction::cast(*value)->IsBuiltin() &&
833 !context().is_null()) {
835 handle(context().ToHandleChecked()->native_context(),
isolate());
836 if (*value == native->math_abs_fun()) {
837 return typer_->number_fun1_;
838 }
else if (*value == native->math_acos_fun()) {
839 return typer_->number_fun1_;
840 }
else if (*value == native->math_asin_fun()) {
841 return typer_->number_fun1_;
842 }
else if (*value == native->math_atan_fun()) {
843 return typer_->number_fun1_;
844 }
else if (*value == native->math_atan2_fun()) {
845 return typer_->number_fun2_;
846 }
else if (*value == native->math_ceil_fun()) {
847 return typer_->weakint_fun1_;
848 }
else if (*value == native->math_cos_fun()) {
849 return typer_->number_fun1_;
850 }
else if (*value == native->math_exp_fun()) {
851 return typer_->number_fun1_;
852 }
else if (*value == native->math_floor_fun()) {
853 return typer_->weakint_fun1_;
854 }
else if (*value == native->math_imul_fun()) {
855 return typer_->imul_fun_;
856 }
else if (*value == native->math_log_fun()) {
857 return typer_->number_fun1_;
858 }
else if (*value == native->math_pow_fun()) {
859 return typer_->number_fun2_;
860 }
else if (*value == native->math_random_fun()) {
861 return typer_->random_fun_;
862 }
else if (*value == native->math_round_fun()) {
863 return typer_->weakint_fun1_;
864 }
else if (*value == native->math_sin_fun()) {
865 return typer_->number_fun1_;
866 }
else if (*value == native->math_sqrt_fun()) {
867 return typer_->number_fun1_;
868 }
else if (*value == native->math_tan_fun()) {
869 return typer_->number_fun1_;
870 }
else if (*value == native->array_buffer_fun()) {
871 return typer_->array_buffer_fun_;
872 }
else if (*value == native->int8_array_fun()) {
873 return typer_->int8_array_fun_;
874 }
else if (*value == native->int16_array_fun()) {
875 return typer_->int16_array_fun_;
876 }
else if (*value == native->int32_array_fun()) {
877 return typer_->int32_array_fun_;
878 }
else if (*value == native->uint8_array_fun()) {
879 return typer_->uint8_array_fun_;
880 }
else if (*value == native->uint16_array_fun()) {
881 return typer_->uint16_array_fun_;
882 }
else if (*value == native->uint32_array_fun()) {
883 return typer_->uint32_array_fun_;
884 }
else if (*value == native->float32_array_fun()) {
885 return typer_->float32_array_fun_;
886 }
else if (*value == native->float64_array_fun()) {
887 return typer_->float64_array_fun_;
899 virtual void Decorate(Node* node) { typer_->Init(node); }
A JavaScript number value (ECMA-262, 4.3.20)
static Handle< T > cast(Handle< S > that)
static TypeHandle Of(double value, Region *region)
static FunctionHandle Function(TypeHandle result, TypeHandle receiver, int arity, Region *region)
static TypeHandle Array(TypeHandle element, Region *region)
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region *reg)
static TypeHandle Range(i::Handle< i::Object > min, i::Handle< i::Object > max, Region *region)
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
static TypeHandle Context(TypeHandle outer, Region *region)
Isolate * isolate() const
void AddDecorator(GraphDecorator *decorator)
void VisitNodeInputsFromEnd(Visitor *visitor)
void VisitNodeUsesFrom(Node *node, Visitor *visitor)
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 bool HasValueOutput(const Operator *op)
static int GetValueInputCount(const Operator *op)
GenericGraphVisit::Control Post(Node *node)
NarrowVisitor(Typer *typer, MaybeHandle< Context > context)
GenericGraphVisit::Control Pre(Node *node)
GenericGraphVisit::Control Post(Node *node)
RunVisitor(Typer *typer, MaybeHandle< Context > context)
Visitor(Typer *typer, MaybeHandle< Context > context)
Type * ContextType(Node *node)
Bounds OperandType(Node *node, int i)
Type * TypeConstant(Handle< Object > value)
Bounds TypeNode(Node *node)
MaybeHandle< Context > context_
MaybeHandle< Context > context()
GenericGraphVisit::Control Post(Node *node)
GenericGraphVisit::Control Pre(Node *node)
WidenVisitor(Typer *typer, MaybeHandle< Context > context)
Type * float32_array_fun_
void Widen(Graph *graph, Node *node, MaybeHandle< Context > context)
Type * float64_array_fun_
void Narrow(Graph *graph, Node *node, MaybeHandle< Context > context)
void Run(Graph *graph, MaybeHandle< Context > context)
void DecorateGraph(Graph *graph)
TyperDecorator(Typer *typer)
virtual void Decorate(Node *node)
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 expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
#define DCHECK(condition)
static M32 s32(int32_t d)
static M32 u32(uint32_t d)
NodeSet::iterator NodeSetIter
const ElementAccess & ElementAccessOf(const Operator *op)
std::set< Node *, std::less< Node * >, zone_allocator< Node * > > NodeSet
const FieldAccess & FieldAccessOf(const Operator *op)
static const T & OpParameter(const Node *node)
TypeImpl< ZoneTypeConfig > Type
kSerializedDataOffset Object
Handle< T > handle(T *t, Isolate *isolate)
BoundsImpl< ZoneTypeConfig > Bounds
Debugger support for the V8 JavaScript engine.
Handle< Primitive > Undefined(Isolate *isolate)
#define JS_COMPARE_BINOP_LIST(V)
#define MACHINE_OP_LIST(V)
#define INNER_CONTROL_OP_LIST(V)
static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region *region)
static BoundsImpl Unbounded(Region *region)
bool Narrows(BoundsImpl that)
static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region *region)
#define DECLARE_METHOD(x)
#define NATIVE_TYPE(sem, rep)