V8 Project
v8::internal::HOptimizedGraphBuilder Class Reference

#include <hydrogen.h>

+ Inheritance diagram for v8::internal::HOptimizedGraphBuilder:
+ Collaboration diagram for v8::internal::HOptimizedGraphBuilder:

Classes

class  BASE_EMBEDDED
 
class  PropertyAccessInfo
 

Public Member Functions

 HOptimizedGraphBuilder (CompilationInfo *info)
 
virtual bool BuildGraph () OVERRIDE
 
BreakAndContinueScope * break_scope () const
 
void set_break_scope (BreakAndContinueScope *head)
 
HValuecontext ()
 
HOsrBuilderosr () const
 
void Bailout (BailoutReason reason)
 
HBasicBlock * CreateJoin (HBasicBlock *first, HBasicBlock *second, BailoutId join_id)
 
FunctionStatefunction_state () const
 
void VisitDeclarations (ZoneList< Declaration * > *declarations)
 
void * operator new (size_t size, Zone *zone)
 
void operator delete (void *pointer, Zone *zone)
 
void operator delete (void *pointer)
 
 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS ()
 
- Public Member Functions inherited from v8::internal::HGraphBuilder
 HGraphBuilder (CompilationInfo *info)
 
virtual ~HGraphBuilder ()
 
Scopescope () const
 
void set_scope (Scope *scope)
 
HBasicBlock * current_block () const
 
void set_current_block (HBasicBlock *block)
 
HEnvironment * environment () const
 
Zonezone () const
 
HGraph * graph () const
 
Isolateisolate () const
 
CompilationInfotop_info ()
 
HGraph * CreateGraph ()
 
void Push (HValue *value)
 
HValuePop ()
 
HInstructionAddInstruction (HInstruction *instr)
 
void FinishCurrentBlock (HControlInstruction *last)
 
void FinishExitCurrentBlock (HControlInstruction *instruction)
 
void Goto (HBasicBlock *from, HBasicBlock *target, FunctionState *state=NULL, bool add_simulate=true)
 
void Goto (HBasicBlock *target, FunctionState *state=NULL, bool add_simulate=true)
 
void GotoNoSimulate (HBasicBlock *from, HBasicBlock *target)
 
void GotoNoSimulate (HBasicBlock *target)
 
void AddLeaveInlined (HBasicBlock *block, HValue *return_value, FunctionState *state)
 
void AddLeaveInlined (HValue *return_value, FunctionState *state)
 
template<class I >
HInstructionNewUncasted ()
 
template<class I >
INew ()
 
template<class I >
HInstructionAddUncasted ()
 
template<class I >
IAdd ()
 
template<class I , class P1 >
HInstructionNewUncasted (P1 p1)
 
template<class I , class P1 >
INew (P1 p1)
 
template<class I , class P1 >
HInstructionAddUncasted (P1 p1)
 
template<class I , class P1 >
IAdd (P1 p1)
 
template<class I , class P1 , class P2 >
HInstructionNewUncasted (P1 p1, P2 p2)
 
template<class I , class P1 , class P2 >
INew (P1 p1, P2 p2)
 
template<class I , class P1 , class P2 >
HInstructionAddUncasted (P1 p1, P2 p2)
 
template<class I , class P1 , class P2 >
IAdd (P1 p1, P2 p2)
 
template<class I , class P1 , class P2 , class P3 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3)
 
template<class I , class P1 , class P2 , class P3 >
INew (P1 p1, P2 p2, P3 p3)
 
template<class I , class P1 , class P2 , class P3 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3)
 
template<class I , class P1 , class P2 , class P3 >
IAdd (P1 p1, P2 p2, P3 p3)
 
template<class I , class P1 , class P2 , class P3 , class P4 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3, P4 p4)
 
template<class I , class P1 , class P2 , class P3 , class P4 >
INew (P1 p1, P2 p2, P3 p3, P4 p4)
 
template<class I , class P1 , class P2 , class P3 , class P4 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3, P4 p4)
 
template<class I , class P1 , class P2 , class P3 , class P4 >
IAdd (P1 p1, P2 p2, P3 p3, P4 p4)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 >
INew (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 >
IAdd (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 >
INew (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 >
IAdd (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 >
INew (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 >
IAdd (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 , class P8 >
HInstructionNewUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 , class P8 >
INew (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 , class P8 >
HInstructionAddUncasted (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
 
template<class I , class P1 , class P2 , class P3 , class P4 , class P5 , class P6 , class P7 , class P8 >
IAdd (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
 
void AddSimulate (BailoutId id, RemovableSimulate removable=FIXED_SIMULATE)
 
template<>
HDeoptimize * Add (const char *reason, Deoptimizer::BailoutType type)
 
template<>
HInstructionAddUncasted (const char *reason, Deoptimizer::BailoutType type)
 
template<>
HSimulate * Add (BailoutId id, RemovableSimulate removable)
 
template<>
HSimulate * Add (BailoutId id)
 
template<>
HInstructionAddUncasted (BailoutId id)
 
template<>
HReturn * Add (HValue *value)
 
template<>
HReturn * Add (HConstant *value)
 
template<>
HInstructionAddUncasted (HValue *value)
 
template<>
HInstructionAddUncasted (HConstant *value)
 
template<>
HCallRuntime * Add (Handle< String > name, const Runtime::Function *c_function, int argument_count)
 
template<>
HInstructionAddUncasted (Handle< String > name, const Runtime::Function *c_function, int argument_count)
 
template<>
HContext * New ()
 
template<>
HInstructionNewUncasted ()
 

Protected Types

typedef void(HOptimizedGraphBuilder::* InlineFunctionGenerator) (CallRuntime *call)
 

Protected Member Functions

void set_function_state (FunctionState *state)
 
AstContextast_context () const
 
void set_ast_context (AstContext *context)
 
CompilationInfocurrent_info () const
 
AstContextcall_context () const
 
HBasicBlock * function_return () const
 
TestContext * inlined_test_context () const
 
void ClearInlinedTestContext ()
 
StrictMode function_strict_mode ()
 
void VisitDelete (UnaryOperation *expr)
 
void VisitVoid (UnaryOperation *expr)
 
void VisitTypeof (UnaryOperation *expr)
 
void VisitNot (UnaryOperation *expr)
 
void VisitComma (BinaryOperation *expr)
 
void VisitLogicalExpression (BinaryOperation *expr)
 
void VisitArithmeticExpression (BinaryOperation *expr)
 
bool PreProcessOsrEntry (IterationStatement *statement)
 
void VisitLoopBody (IterationStatement *stmt, HBasicBlock *loop_entry)
 
HBasicBlock * CreateLoop (IterationStatement *statement, HBasicBlock *loop_entry, HBasicBlock *body_exit, HBasicBlock *loop_successor, HBasicBlock *break_block)
 
HBasicBlock * BuildLoopEntry ()
 
HBasicBlock * BuildLoopEntry (IterationStatement *statement)
 
HBasicBlock * JoinContinue (IterationStatement *statement, HBasicBlock *exit_block, HBasicBlock *continue_block)
 
HValueTop () const
 
void Drop (int n)
 
void Bind (Variable *var, HValue *value)
 
bool IsEligibleForEnvironmentLivenessAnalysis (Variable *var, int index, HValue *value, HEnvironment *env)
 
void BindIfLive (Variable *var, HValue *value)
 
HValueLookupAndMakeLive (Variable *var)
 
void VisitForValue (Expression *expr, ArgumentsAllowedFlag flag=ARGUMENTS_NOT_ALLOWED)
 
void VisitForTypeOf (Expression *expr)
 
void VisitForEffect (Expression *expr)
 
void VisitForControl (Expression *expr, HBasicBlock *true_block, HBasicBlock *false_block)
 
void VisitExpressions (ZoneList< Expression * > *exprs)
 
template<class Instruction >
HInstructionPreProcessCall (Instruction *call)
 
void PushArgumentsFromEnvironment (int count)
 
void SetUpScope (Scope *scope)
 
virtual void VisitStatements (ZoneList< Statement * > *statements) OVERRIDE
 
TypeToType (Handle< Map > map)
 
- Protected Member Functions inherited from v8::internal::HGraphBuilder
HBasicBlock * CreateBasicBlock (HEnvironment *env)
 
HBasicBlock * CreateLoopHeaderBlock ()
 
template<class BitFieldClass >
HValueBuildDecodeField (HValue *encoded_field)
 
HValueBuildGetElementsKind (HValue *object)
 
HValueBuildCheckHeapObject (HValue *object)
 
HValueBuildCheckString (HValue *string)
 
HValueBuildWrapReceiver (HValue *object, HValue *function)
 
HValueBuildCheckForCapacityGrow (HValue *object, HValue *elements, ElementsKind kind, HValue *length, HValue *key, bool is_js_array, PropertyAccessType access_type)
 
HValueBuildCopyElementsOnWrite (HValue *object, HValue *elements, ElementsKind kind, HValue *length)
 
void BuildTransitionElementsKind (HValue *object, HValue *map, ElementsKind from_kind, ElementsKind to_kind, bool is_jsarray)
 
HValueBuildNumberToString (HValue *object, Type *type)
 
void BuildJSObjectCheck (HValue *receiver, int bit_field_mask)
 
void BuildKeyedIndexCheck (HValue *key, HIfContinuation *join_continuation)
 
void BuildTestForDictionaryProperties (HValue *object, HIfContinuation *continuation)
 
void BuildNonGlobalObjectCheck (HValue *receiver)
 
HValueBuildKeyedLookupCacheHash (HValue *object, HValue *key)
 
HValueBuildUncheckedDictionaryElementLoad (HValue *receiver, HValue *elements, HValue *key, HValue *hash)
 
HValueBuildRegExpConstructResult (HValue *length, HValue *index, HValue *input)
 
HAllocate * BuildAllocate (HValue *object_size, HType type, InstanceType instance_type, HAllocationMode allocation_mode)
 
HValueBuildAddStringLengths (HValue *left_length, HValue *right_length)
 
HValueBuildCreateConsString (HValue *length, HValue *left, HValue *right, HAllocationMode allocation_mode)
 
void BuildCopySeqStringChars (HValue *src, HValue *src_offset, String::Encoding src_encoding, HValue *dst, HValue *dst_offset, String::Encoding dst_encoding, HValue *length)
 
HValueBuildObjectSizeAlignment (HValue *unaligned_size, int header_size)
 
HValueBuildUncheckedStringAdd (HValue *left, HValue *right, HAllocationMode allocation_mode)
 
HValueBuildStringAdd (HValue *left, HValue *right, HAllocationMode allocation_mode)
 
HInstructionBuildUncheckedMonomorphicElementAccess (HValue *checked_object, HValue *key, HValue *val, bool is_js_array, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode, KeyedAccessStoreMode store_mode)
 
HInstructionAddElementAccess (HValue *elements, HValue *checked_key, HValue *val, HValue *dependency, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode=NEVER_RETURN_HOLE)
 
HInstructionAddLoadStringInstanceType (HValue *string)
 
HInstructionAddLoadStringLength (HValue *string)
 
HStoreNamedField * AddStoreMapConstant (HValue *object, Handle< Map > map)
 
HLoadNamedField * AddLoadMap (HValue *object, HValue *dependency=NULL)
 
HLoadNamedField * AddLoadElements (HValue *object, HValue *dependency=NULL)
 
bool MatchRotateRight (HValue *left, HValue *right, HValue **operand, HValue **shift_amount)
 
HValueBuildBinaryOperation (Token::Value op, HValue *left, HValue *right, Type *left_type, Type *right_type, Type *result_type, Maybe< int > fixed_right_arg, HAllocationMode allocation_mode)
 
HLoadNamedField * AddLoadFixedArrayLength (HValue *object, HValue *dependency=NULL)
 
HLoadNamedField * AddLoadArrayLength (HValue *object, ElementsKind kind, HValue *dependency=NULL)
 
HValueAddLoadJSBuiltin (Builtins::JavaScript builtin)
 
HValueEnforceNumberType (HValue *number, Type *expected)
 
HValueTruncateToNumber (HValue *value, Type **expected)
 
void FinishExitWithHardDeoptimization (const char *reason)
 
void AddIncrementCounter (StatsCounter *counter)
 
HValueBuildNewElementsCapacity (HValue *old_capacity)
 
HValueBuildAllocateArrayFromLength (JSArrayBuilder *array_builder, HValue *length_argument)
 
HValueBuildCalculateElementsSize (ElementsKind kind, HValue *capacity)
 
HAllocate * AllocateJSArrayObject (AllocationSiteMode mode)
 
HConstant * EstablishElementsAllocationSize (ElementsKind kind, int capacity)
 
HAllocate * BuildAllocateElements (ElementsKind kind, HValue *size_in_bytes)
 
void BuildInitializeElementsHeader (HValue *elements, ElementsKind kind, HValue *capacity)
 
HValueBuildAllocateElementsAndInitializeElementsHeader (ElementsKind kind, HValue *capacity)
 
void BuildJSArrayHeader (HValue *array, HValue *array_map, HValue *elements, AllocationSiteMode mode, ElementsKind elements_kind, HValue *allocation_site_payload, HValue *length_field)
 
HValueBuildGrowElementsCapacity (HValue *object, HValue *elements, ElementsKind kind, ElementsKind new_kind, HValue *length, HValue *new_capacity)
 
void BuildFillElementsWithValue (HValue *elements, ElementsKind elements_kind, HValue *from, HValue *to, HValue *value)
 
void BuildFillElementsWithHole (HValue *elements, ElementsKind elements_kind, HValue *from, HValue *to)
 
void BuildCopyElements (HValue *from_elements, ElementsKind from_elements_kind, HValue *to_elements, ElementsKind to_elements_kind, HValue *length, HValue *capacity)
 
HValueBuildCloneShallowArrayCow (HValue *boilerplate, HValue *allocation_site, AllocationSiteMode mode, ElementsKind kind)
 
HValueBuildCloneShallowArrayEmpty (HValue *boilerplate, HValue *allocation_site, AllocationSiteMode mode)
 
HValueBuildCloneShallowArrayNonEmpty (HValue *boilerplate, HValue *allocation_site, AllocationSiteMode mode, ElementsKind kind)
 
HValueBuildElementIndexHash (HValue *index)
 
void BuildCompareNil (HValue *value, Type *type, HIfContinuation *continuation)
 
void BuildCreateAllocationMemento (HValue *previous_object, HValue *previous_object_size, HValue *payload)
 
HInstructionBuildConstantMapCheck (Handle< JSObject > constant)
 
HInstructionBuildCheckPrototypeMaps (Handle< JSObject > prototype, Handle< JSObject > holder)
 
HInstructionBuildGetNativeContext (HValue *closure)
 
HInstructionBuildGetNativeContext ()
 
HInstructionBuildGetArrayFunction ()
 
void SetSourcePosition (int position)
 
void EnterInlinedSource (int start_position, int id)
 
HSourcePosition ScriptPositionToSourcePosition (int position)
 
HSourcePosition source_position ()
 
void set_source_position (HSourcePosition position)
 
template<typename ViewClass >
void BuildArrayBufferViewInitialization (HValue *obj, HValue *buffer, HValue *byte_offset, HValue *byte_length)
 

Static Protected Attributes

static const InlineFunctionGenerator kInlineFunctionGenerators []
 
static const int kMaxCallPolymorphism = 4
 
static const int kMaxLoadPolymorphism = 4
 
static const int kMaxStorePolymorphism = 4
 
static const int kUnlimitedMaxInlinedSourceSize = 100000
 
static const int kUnlimitedMaxInlinedNodes = 10000
 
static const int kUnlimitedMaxInlinedNodesCumulative = 10000
 
static const int kMaxFastLiteralDepth = 3
 
static const int kMaxFastLiteralProperties = 8
 

Private Types

enum  GlobalPropertyAccess { kUseCell , kUseGeneric }
 
enum  ArrayIndexOfMode { kFirstIndexOf , kLastIndexOf }
 
enum  ApiCallType { kCallApiFunction , kCallApiMethod , kCallApiGetter , kCallApiSetter }
 
enum  PushBeforeSimulateBehavior { PUSH_BEFORE_SIMULATE , NO_PUSH_BEFORE_SIMULATE }
 

Private Member Functions

GlobalPropertyAccess LookupGlobalProperty (Variable *var, LookupIterator *it, PropertyAccessType access_type)
 
void EnsureArgumentsArePushedForAccess ()
 
bool TryArgumentsAccess (Property *expr)
 
bool TryCallApply (Call *expr)
 
bool TryHandleArrayCall (Call *expr, HValue *function)
 
bool TryHandleArrayCallNew (CallNew *expr, HValue *function)
 
void BuildArrayCall (Expression *expr, int arguments_count, HValue *function, Handle< AllocationSite > cell)
 
HValueBuildArrayIndexOf (HValue *receiver, HValue *search_element, ElementsKind kind, ArrayIndexOfMode mode)
 
HValueImplicitReceiverFor (HValue *function, Handle< JSFunction > target)
 
int InliningAstSize (Handle< JSFunction > target)
 
bool TryInline (Handle< JSFunction > target, int arguments_count, HValue *implicit_return_value, BailoutId ast_id, BailoutId return_id, InliningKind inlining_kind, HSourcePosition position)
 
bool TryInlineCall (Call *expr)
 
bool TryInlineConstruct (CallNew *expr, HValue *implicit_return_value)
 
bool TryInlineGetter (Handle< JSFunction > getter, Handle< Map > receiver_map, BailoutId ast_id, BailoutId return_id)
 
bool TryInlineSetter (Handle< JSFunction > setter, Handle< Map > receiver_map, BailoutId id, BailoutId assignment_id, HValue *implicit_return_value)
 
bool TryInlineApply (Handle< JSFunction > function, Call *expr, int arguments_count)
 
bool TryInlineBuiltinMethodCall (Call *expr, HValue *receiver, Handle< Map > receiver_map)
 
bool TryInlineBuiltinFunctionCall (Call *expr)
 
bool TryInlineApiMethodCall (Call *expr, HValue *receiver, SmallMapList *receiver_types)
 
bool TryInlineApiFunctionCall (Call *expr, HValue *receiver)
 
bool TryInlineApiGetter (Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
 
bool TryInlineApiSetter (Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
 
bool TryInlineApiCall (Handle< JSFunction > function, HValue *receiver, SmallMapList *receiver_maps, int argc, BailoutId ast_id, ApiCallType call_type)
 
void TraceInline (Handle< JSFunction > target, Handle< JSFunction > caller, const char *failure_reason)
 
void HandleGlobalVariableAssignment (Variable *var, HValue *value, BailoutId ast_id)
 
void HandlePropertyAssignment (Assignment *expr)
 
void HandleCompoundAssignment (Assignment *expr)
 
void HandlePolymorphicNamedFieldAccess (PropertyAccessType access_type, Expression *expr, BailoutId ast_id, BailoutId return_id, HValue *object, HValue *value, SmallMapList *types, Handle< String > name)
 
HValueBuildAllocateExternalElements (ExternalArrayType array_type, bool is_zero_byte_offset, HValue *buffer, HValue *byte_offset, HValue *length)
 
HValueBuildAllocateFixedTypedArray (ExternalArrayType array_type, size_t element_size, ElementsKind fixed_elements_kind, HValue *byte_length, HValue *length)
 
Handle< JSFunctionarray_function ()
 
bool IsCallArrayInlineable (int argument_count, Handle< AllocationSite > site)
 
void BuildInlinedCallArray (Expression *expression, int argument_count, Handle< AllocationSite > site)
 
HInstructionBuildMonomorphicAccess (PropertyAccessInfo *info, HValue *object, HValue *checked_object, HValue *value, BailoutId ast_id, BailoutId return_id, bool can_inline_accessor=true)
 
HInstructionBuildNamedAccess (PropertyAccessType access, BailoutId ast_id, BailoutId reutrn_id, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
 
void HandlePolymorphicCallNamed (Call *expr, HValue *receiver, SmallMapList *types, Handle< String > name)
 
void HandleLiteralCompareTypeof (CompareOperation *expr, Expression *sub_expr, Handle< String > check)
 
void HandleLiteralCompareNil (CompareOperation *expr, Expression *sub_expr, NilValue nil)
 
HControlInstructionBuildCompareInstruction (Token::Value op, HValue *left, HValue *right, Type *left_type, Type *right_type, Type *combined_type, HSourcePosition left_position, HSourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, BailoutId bailout_id)
 
HInstructionBuildStringCharCodeAt (HValue *string, HValue *index)
 
HValueBuildBinaryOperation (BinaryOperation *expr, HValue *left, HValue *right, PushBeforeSimulateBehavior push_sim_result)
 
HInstructionBuildIncrement (bool returns_original_input, CountOperation *expr)
 
HInstructionBuildKeyedGeneric (PropertyAccessType access_type, Expression *expr, HValue *object, HValue *key, HValue *value)
 
HInstructionTryBuildConsolidatedElementLoad (HValue *object, HValue *key, HValue *val, SmallMapList *maps)
 
LoadKeyedHoleMode BuildKeyedHoleMode (Handle< Map > map)
 
HInstructionBuildMonomorphicElementAccess (HValue *object, HValue *key, HValue *val, HValue *dependency, Handle< Map > map, PropertyAccessType access_type, KeyedAccessStoreMode store_mode)
 
HValueHandlePolymorphicElementAccess (Expression *expr, HValue *object, HValue *key, HValue *val, SmallMapList *maps, PropertyAccessType access_type, KeyedAccessStoreMode store_mode, bool *has_side_effects)
 
HValueHandleKeyedElementAccess (HValue *obj, HValue *key, HValue *val, Expression *expr, BailoutId ast_id, BailoutId return_id, PropertyAccessType access_type, bool *has_side_effects)
 
HInstructionBuildNamedGeneric (PropertyAccessType access, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
 
HCheckMaps * AddCheckMap (HValue *object, Handle< Map > map)
 
void BuildLoad (Property *property, BailoutId ast_id)
 
void PushLoad (Property *property, HValue *object, HValue *key)
 
void BuildStoreForEffect (Expression *expression, Property *prop, BailoutId ast_id, BailoutId return_id, HValue *object, HValue *key, HValue *value)
 
void BuildStore (Expression *expression, Property *prop, BailoutId ast_id, BailoutId return_id, bool is_uninitialized=false)
 
HInstructionBuildLoadNamedField (PropertyAccessInfo *info, HValue *checked_object)
 
HInstructionBuildStoreNamedField (PropertyAccessInfo *info, HValue *checked_object, HValue *value)
 
HValueBuildContextChainWalk (Variable *var)
 
HInstructionBuildThisFunction ()
 
HInstructionBuildFastLiteral (Handle< JSObject > boilerplate_object, AllocationSiteUsageContext *site_context)
 
void BuildEmitObjectHeader (Handle< JSObject > boilerplate_object, HInstruction *object)
 
void BuildInitElementsInObjectHeader (Handle< JSObject > boilerplate_object, HInstruction *object, HInstruction *object_elements)
 
void BuildEmitInObjectProperties (Handle< JSObject > boilerplate_object, HInstruction *object, AllocationSiteUsageContext *site_context, PretenureFlag pretenure_flag)
 
void BuildEmitElements (Handle< JSObject > boilerplate_object, Handle< FixedArrayBase > elements, HValue *object_elements, AllocationSiteUsageContext *site_context)
 
void BuildEmitFixedDoubleArray (Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements)
 
void BuildEmitFixedArray (Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements, AllocationSiteUsageContext *site_context)
 
void AddCheckPrototypeMaps (Handle< JSObject > holder, Handle< Map > receiver_map)
 
HInstructionNewPlainFunctionCall (HValue *fun, int argument_count, bool pass_argument_count)
 
HInstructionNewArgumentAdaptorCall (HValue *fun, HValue *context, int argument_count, HValue *expected_param_count)
 
HInstructionBuildCallConstantFunction (Handle< JSFunction > target, int argument_count)
 
 DISALLOW_COPY_AND_ASSIGN (HOptimizedGraphBuilder)
 

Private Attributes

FunctionStatefunction_state_
 
FunctionState initial_function_state_
 
AstContextast_context_
 
BreakAndContinueScope * break_scope_
 
int inlined_count_
 
ZoneList< Handle< Object > > globals_
 
bool inline_bailout_
 
HOsrBuilderosr_
 

Friends

class FunctionState
 
class AstContext
 
class KeyedLoadFastElementStub
 
class HOsrBuilder
 

Additional Inherited Members

- Static Public Attributes inherited from v8::internal::HGraphBuilder
static const int kElementLoopUnrollThreshold = 8
 

Detailed Description

Definition at line 2045 of file hydrogen.h.

Member Typedef Documentation

◆ InlineFunctionGenerator

typedef void(HOptimizedGraphBuilder::* v8::internal::HOptimizedGraphBuilder::InlineFunctionGenerator) (CallRuntime *call)
protected

Definition at line 2137 of file hydrogen.h.

Member Enumeration Documentation

◆ ApiCallType

Enumerator
kCallApiFunction 
kCallApiMethod 
kCallApiGetter 
kCallApiSetter 

Definition at line 2358 of file hydrogen.h.

◆ ArrayIndexOfMode

Enumerator
kFirstIndexOf 
kLastIndexOf 

Definition at line 2322 of file hydrogen.h.

◆ GlobalPropertyAccess

Enumerator
kUseCell 
kUseGeneric 

Definition at line 2304 of file hydrogen.h.

◆ PushBeforeSimulateBehavior

Enumerator
PUSH_BEFORE_SIMULATE 
NO_PUSH_BEFORE_SIMULATE 

Definition at line 2571 of file hydrogen.h.

Constructor & Destructor Documentation

◆ HOptimizedGraphBuilder()

v8::internal::HOptimizedGraphBuilder::HOptimizedGraphBuilder ( CompilationInfo info)
explicit

Definition at line 3321 of file hydrogen.cc.

3322  : HGraphBuilder(info),
3324  initial_function_state_(this, info, NORMAL_RETURN, 0),
3325  ast_context_(NULL),
3326  break_scope_(NULL),
3327  inlined_count_(0),
3328  globals_(10, info->zone()),
3329  osr_(new(info->zone()) HOsrBuilder(this)) {
3330  // This is not initialized in the initializer list because the
3331  // constructor for the initial state relies on function_state_ == NULL
3332  // to know it's the initial state.
3334  InitializeAstVisitor(info->zone());
3335  if (FLAG_hydrogen_track_positions) {
3336  SetSourcePosition(info->shared_info()->start_position());
3337  }
3338 }
void SetSourcePosition(int position)
Definition: hydrogen.h:1882
BreakAndContinueScope * break_scope_
Definition: hydrogen.h:2727
ZoneList< Handle< Object > > globals_
Definition: hydrogen.h:2730
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

References function_state_, initial_function_state_, v8::internal::HGraphBuilder::SetSourcePosition(), v8::internal::CompilationInfo::shared_info(), and v8::internal::CompilationInfo::zone().

+ Here is the call graph for this function:

Member Function Documentation

◆ AddCheckMap()

HCheckMaps * v8::internal::HOptimizedGraphBuilder::AddCheckMap ( HValue object,
Handle< Map map 
)
private

Definition at line 5797 of file hydrogen.cc.

5798  {
5799  BuildCheckHeapObject(object);
5800  return Add<HCheckMaps>(object, map);
5801 }
HValue * BuildCheckHeapObject(HValue *object)
Definition: hydrogen.cc:1266
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 map

References v8::internal::HGraphBuilder::BuildCheckHeapObject(), and map.

Referenced by BuildCompareInstruction(), TryCallApply(), and TryInlineBuiltinMethodCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddCheckPrototypeMaps()

void v8::internal::HOptimizedGraphBuilder::AddCheckPrototypeMaps ( Handle< JSObject holder,
Handle< Map receiver_map 
)
private

Definition at line 7421 of file hydrogen.cc.

7422  {
7423  if (!holder.is_null()) {
7424  Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7425  BuildCheckPrototypeMaps(prototype, holder);
7426  }
7427 }
HInstruction * BuildCheckPrototypeMaps(Handle< JSObject > prototype, Handle< JSObject > holder)
Definition: hydrogen.cc:7403

References v8::internal::HGraphBuilder::BuildCheckPrototypeMaps(), and v8::internal::Handle< T >::is_null().

Referenced by HandlePolymorphicCallNamed(), and TryInlineApiCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ array_function()

Handle<JSFunction> v8::internal::HOptimizedGraphBuilder::array_function ( )
inlineprivate

Definition at line 2412 of file hydrogen.h.

2412  {
2413  return handle(isolate()->native_context()->array_function());
2414  }
Isolate * isolate() const
Definition: hydrogen.h:1064
Handle< JSFunction > array_function()
Definition: hydrogen.h:2412
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146

References v8::internal::handle(), and v8::internal::HGraphBuilder::isolate().

Referenced by BuildArrayCall(), IsCallArrayInlineable(), TryHandleArrayCall(), and TryHandleArrayCallNew().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ast_context()

AstContext* v8::internal::HOptimizedGraphBuilder::ast_context ( ) const
inlineprotected

◆ Bailout()

void v8::internal::HOptimizedGraphBuilder::Bailout ( BailoutReason  reason)

Definition at line 4212 of file hydrogen.cc.

4212  {
4213  current_info()->AbortOptimization(reason);
4214  SetStackOverflow();
4215 }
void AbortOptimization(BailoutReason reason)
Definition: compiler.h:330
CompilationInfo * current_info() const
Definition: hydrogen.h:2167

References v8::internal::CompilationInfo::AbortOptimization(), and current_info().

Referenced by BuildCompareInstruction(), BuildGraph(), HandleCompoundAssignment(), v8::internal::OptimizedCompileJob::OptimizeGraph(), SetUpScope(), and VisitDelete().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Bind()

void v8::internal::HOptimizedGraphBuilder::Bind ( Variable var,
HValue value 
)
inlineprotected

Definition at line 2232 of file hydrogen.h.

2232 { environment()->Bind(var, value); }
HEnvironment * environment() const
Definition: hydrogen.h:1059

References v8::internal::HGraphBuilder::environment().

+ Here is the call graph for this function:

◆ BindIfLive()

void v8::internal::HOptimizedGraphBuilder::BindIfLive ( Variable var,
HValue value 
)
inlineprotected

Definition at line 2245 of file hydrogen.h.

2245  {
2246  HEnvironment* env = environment();
2247  int index = env->IndexFor(var);
2248  env->Bind(index, value);
2249  if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2250  HEnvironmentMarker* bind =
2251  Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2252  USE(bind);
2253 #ifdef DEBUG
2254  bind->set_closure(env->closure());
2255 #endif
2256  }
2257  }
bool IsEligibleForEnvironmentLivenessAnalysis(Variable *var, int index, HValue *value, HEnvironment *env)
Definition: hydrogen.h:2233
void USE(T)
Definition: macros.h:322

References v8::internal::HGraphBuilder::environment(), IsEligibleForEnvironmentLivenessAnalysis(), and USE().

Referenced by HandleCompoundAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ break_scope()

BreakAndContinueScope* v8::internal::HOptimizedGraphBuilder::break_scope ( ) const
inline

Definition at line 2110 of file hydrogen.h.

2110 { return break_scope_; }

References break_scope_.

◆ BuildAllocateExternalElements()

HValue * v8::internal::HOptimizedGraphBuilder::BuildAllocateExternalElements ( ExternalArrayType  array_type,
bool  is_zero_byte_offset,
HValue buffer,
HValue byte_offset,
HValue length 
)
private

Definition at line 9489 of file hydrogen.cc.

9492  {
9493  Handle<Map> external_array_map(
9494  isolate()->heap()->MapForExternalArrayType(array_type));
9495 
9496  // The HForceRepresentation is to prevent possible deopt on int-smi
9497  // conversion after allocation but before the new object fields are set.
9498  length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9499  HValue* elements =
9500  Add<HAllocate>(
9501  Add<HConstant>(ExternalArray::kAlignedSize),
9502  HType::HeapObject(),
9503  NOT_TENURED,
9504  external_array_map->instance_type());
9505 
9506  AddStoreMapConstant(elements, external_array_map);
9507  Add<HStoreNamedField>(elements,
9508  HObjectAccess::ForFixedArrayLength(), length);
9509 
9510  HValue* backing_store = Add<HLoadNamedField>(
9511  buffer, static_cast<HValue*>(NULL),
9512  HObjectAccess::ForJSArrayBufferBackingStore());
9513 
9514  HValue* typed_array_start;
9515  if (is_zero_byte_offset) {
9516  typed_array_start = backing_store;
9517  } else {
9518  HInstruction* external_pointer =
9519  AddUncasted<HAdd>(backing_store, byte_offset);
9520  // Arguments are checked prior to call to TypedArrayInitialize,
9521  // including byte_offset.
9522  external_pointer->ClearFlag(HValue::kCanOverflow);
9523  typed_array_start = external_pointer;
9524  }
9525 
9526  Add<HStoreNamedField>(elements,
9527  HObjectAccess::ForExternalArrayExternalPointer(),
9528  typed_array_start);
9529 
9530  return elements;
9531 }
static const int kAlignedSize
Definition: objects.h:4474
HStoreNamedField * AddStoreMapConstant(HValue *object, Handle< Map > map)
Definition: hydrogen.h:1438
static Representation Smi()

References v8::internal::HGraphBuilder::AddStoreMapConstant(), v8::internal::HValue::ClearFlag(), v8::internal::HGraphBuilder::isolate(), v8::internal::ExternalArray::kAlignedSize, v8::internal::HValue::kCanOverflow, v8::internal::NOT_TENURED, NULL, and v8::internal::Representation::Smi().

+ Here is the call graph for this function:

◆ BuildAllocateFixedTypedArray()

HValue * v8::internal::HOptimizedGraphBuilder::BuildAllocateFixedTypedArray ( ExternalArrayType  array_type,
size_t  element_size,
ElementsKind  fixed_elements_kind,
HValue byte_length,
HValue length 
)
private

Definition at line 9534 of file hydrogen.cc.

9537  {
9538  STATIC_ASSERT(
9540  HValue* total_size;
9541 
9542  // if fixed array's elements are not aligned to object's alignment,
9543  // we need to align the whole array to object alignment.
9544  if (element_size % kObjectAlignment != 0) {
9545  total_size = BuildObjectSizeAlignment(
9546  byte_length, FixedTypedArrayBase::kHeaderSize);
9547  } else {
9548  total_size = AddUncasted<HAdd>(byte_length,
9549  Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
9550  total_size->ClearFlag(HValue::kCanOverflow);
9551  }
9552 
9553  // The HForceRepresentation is to prevent possible deopt on int-smi
9554  // conversion after allocation but before the new object fields are set.
9555  length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9556  Handle<Map> fixed_typed_array_map(
9557  isolate()->heap()->MapForFixedTypedArray(array_type));
9558  HValue* elements =
9559  Add<HAllocate>(total_size, HType::HeapObject(),
9560  NOT_TENURED, fixed_typed_array_map->instance_type());
9561  AddStoreMapConstant(elements, fixed_typed_array_map);
9562 
9563  Add<HStoreNamedField>(elements,
9564  HObjectAccess::ForFixedArrayLength(),
9565  length);
9566 
9567  HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
9568 
9569  {
9570  LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
9571 
9572  HValue* key = builder.BeginBody(
9573  Add<HConstant>(static_cast<int32_t>(0)),
9574  length, Token::LT);
9575  Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
9576 
9577  builder.EndBody();
9578  }
9579  return elements;
9580 }
static const int kHeaderSize
Definition: objects.h:2393
HValue * BuildObjectSizeAlignment(HValue *unaligned_size, int header_size)
Definition: hydrogen.cc:2167
int int32_t
Definition: unicode.cc:24
const intptr_t kObjectAlignmentMask
Definition: globals.h:227
const intptr_t kObjectAlignment
Definition: globals.h:226
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))

References v8::internal::HGraphBuilder::AddStoreMapConstant(), v8::internal::HGraphBuilder::BuildObjectSizeAlignment(), v8::internal::HValue::ClearFlag(), context(), v8::internal::HGraphBuilder::isolate(), v8::internal::HValue::kCanOverflow, v8::internal::FixedArrayBase::kHeaderSize, v8::internal::kObjectAlignment, v8::internal::kObjectAlignmentMask, v8::internal::NOT_TENURED, v8::internal::Representation::Smi(), and v8::internal::STATIC_ASSERT().

+ Here is the call graph for this function:

◆ BuildArrayCall()

void v8::internal::HOptimizedGraphBuilder::BuildArrayCall ( Expression expr,
int  arguments_count,
HValue function,
Handle< AllocationSite cell 
)
private

Definition at line 8781 of file hydrogen.cc.

8784  {
8785  Add<HCheckValue>(function, array_function());
8786 
8787  if (IsCallArrayInlineable(arguments_count, site)) {
8788  BuildInlinedCallArray(expression, arguments_count, site);
8789  return;
8790  }
8791 
8792  HInstruction* call = PreProcessCall(New<HCallNewArray>(
8793  function, arguments_count + 1, site->GetElementsKind()));
8794  if (expression->IsCall()) {
8795  Drop(1);
8796  }
8797  ast_context()->ReturnInstruction(call, expression->id());
8798 }
virtual void ReturnInstruction(HInstruction *instr, BailoutId ast_id)=0
bool IsCallArrayInlineable(int argument_count, Handle< AllocationSite > site)
Definition: hydrogen.cc:9217
AstContext * ast_context() const
Definition: hydrogen.h:2163
HInstruction * PreProcessCall(Instruction *call)
Definition: hydrogen.cc:4468
void BuildInlinedCallArray(Expression *expression, int argument_count, Handle< AllocationSite > site)
Definition: hydrogen.cc:9161

References array_function(), ast_context(), BuildInlinedCallArray(), Drop(), v8::internal::Expression::id(), IsCallArrayInlineable(), PreProcessCall(), and v8::internal::AstContext::ReturnInstruction().

Referenced by TryHandleArrayCall(), and TryHandleArrayCallNew().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildArrayIndexOf()

HValue * v8::internal::HOptimizedGraphBuilder::BuildArrayIndexOf ( HValue receiver,
HValue search_element,
ElementsKind  kind,
ArrayIndexOfMode  mode 
)
private

Definition at line 8801 of file hydrogen.cc.

8804  {
8805  DCHECK(IsFastElementsKind(kind));
8806 
8807  NoObservableSideEffectsScope no_effects(this);
8808 
8809  HValue* elements = AddLoadElements(receiver);
8810  HValue* length = AddLoadArrayLength(receiver, kind);
8811 
8812  HValue* initial;
8813  HValue* terminating;
8814  Token::Value token;
8815  LoopBuilder::Direction direction;
8816  if (mode == kFirstIndexOf) {
8817  initial = graph()->GetConstant0();
8818  terminating = length;
8819  token = Token::LT;
8820  direction = LoopBuilder::kPostIncrement;
8821  } else {
8823  initial = length;
8824  terminating = graph()->GetConstant0();
8825  token = Token::GT;
8826  direction = LoopBuilder::kPreDecrement;
8827  }
8828 
8829  Push(graph()->GetConstantMinus1());
8830  if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
8831  // Make sure that we can actually compare numbers correctly below, see
8832  // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
8833  search_element = AddUncasted<HForceRepresentation>(
8834  search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
8836 
8837  LoopBuilder loop(this, context(), direction);
8838  {
8839  HValue* index = loop.BeginBody(initial, terminating, token);
8840  HValue* element = AddUncasted<HLoadKeyed>(
8841  elements, index, static_cast<HValue*>(NULL),
8842  kind, ALLOW_RETURN_HOLE);
8843  IfBuilder if_issame(this);
8844  if_issame.If<HCompareNumericAndBranch>(element, search_element,
8845  Token::EQ_STRICT);
8846  if_issame.Then();
8847  {
8848  Drop(1);
8849  Push(index);
8850  loop.Break();
8851  }
8852  if_issame.End();
8853  }
8854  loop.EndBody();
8855  } else {
8856  IfBuilder if_isstring(this);
8857  if_isstring.If<HIsStringAndBranch>(search_element);
8858  if_isstring.Then();
8859  {
8860  LoopBuilder loop(this, context(), direction);
8861  {
8862  HValue* index = loop.BeginBody(initial, terminating, token);
8863  HValue* element = AddUncasted<HLoadKeyed>(
8864  elements, index, static_cast<HValue*>(NULL),
8865  kind, ALLOW_RETURN_HOLE);
8866  IfBuilder if_issame(this);
8867  if_issame.If<HIsStringAndBranch>(element);
8868  if_issame.AndIf<HStringCompareAndBranch>(
8869  element, search_element, Token::EQ_STRICT);
8870  if_issame.Then();
8871  {
8872  Drop(1);
8873  Push(index);
8874  loop.Break();
8875  }
8876  if_issame.End();
8877  }
8878  loop.EndBody();
8879  }
8880  if_isstring.Else();
8881  {
8882  IfBuilder if_isnumber(this);
8883  if_isnumber.If<HIsSmiAndBranch>(search_element);
8884  if_isnumber.OrIf<HCompareMap>(
8885  search_element, isolate()->factory()->heap_number_map());
8886  if_isnumber.Then();
8887  {
8888  HValue* search_number =
8889  AddUncasted<HForceRepresentation>(search_element,
8891  LoopBuilder loop(this, context(), direction);
8892  {
8893  HValue* index = loop.BeginBody(initial, terminating, token);
8894  HValue* element = AddUncasted<HLoadKeyed>(
8895  elements, index, static_cast<HValue*>(NULL),
8896  kind, ALLOW_RETURN_HOLE);
8897 
8898  IfBuilder if_element_isnumber(this);
8899  if_element_isnumber.If<HIsSmiAndBranch>(element);
8900  if_element_isnumber.OrIf<HCompareMap>(
8901  element, isolate()->factory()->heap_number_map());
8902  if_element_isnumber.Then();
8903  {
8904  HValue* number =
8905  AddUncasted<HForceRepresentation>(element,
8907  IfBuilder if_issame(this);
8908  if_issame.If<HCompareNumericAndBranch>(
8909  number, search_number, Token::EQ_STRICT);
8910  if_issame.Then();
8911  {
8912  Drop(1);
8913  Push(index);
8914  loop.Break();
8915  }
8916  if_issame.End();
8917  }
8918  if_element_isnumber.End();
8919  }
8920  loop.EndBody();
8921  }
8922  if_isnumber.Else();
8923  {
8924  LoopBuilder loop(this, context(), direction);
8925  {
8926  HValue* index = loop.BeginBody(initial, terminating, token);
8927  HValue* element = AddUncasted<HLoadKeyed>(
8928  elements, index, static_cast<HValue*>(NULL),
8929  kind, ALLOW_RETURN_HOLE);
8930  IfBuilder if_issame(this);
8931  if_issame.If<HCompareObjectEqAndBranch>(
8932  element, search_element);
8933  if_issame.Then();
8934  {
8935  Drop(1);
8936  Push(index);
8937  loop.Break();
8938  }
8939  if_issame.End();
8940  }
8941  loop.EndBody();
8942  }
8943  if_isnumber.End();
8944  }
8945  if_isstring.End();
8946  }
8947 
8948  return Pop();
8949 }
void Push(HValue *value)
Definition: hydrogen.h:1070
HLoadNamedField * AddLoadElements(HValue *object, HValue *dependency=NULL)
Definition: hydrogen.cc:2708
HLoadNamedField * AddLoadArrayLength(HValue *object, ElementsKind kind, HValue *dependency=NULL)
Definition: hydrogen.cc:2723
HGraph * graph() const
Definition: hydrogen.h:1063
Factory * factory()
Definition: isolate.h:982
static Representation Double()
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 mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
bool IsFastDoubleElementsKind(ElementsKind kind)
bool IsFastElementsKind(ElementsKind kind)
bool IsFastSmiElementsKind(ElementsKind kind)

References v8::internal::HGraphBuilder::AddLoadArrayLength(), v8::internal::HGraphBuilder::AddLoadElements(), v8::internal::ALLOW_RETURN_HOLE, context(), DCHECK, DCHECK_EQ, v8::internal::Representation::Double(), Drop(), v8::internal::Isolate::factory(), v8::internal::HGraphBuilder::graph(), v8::internal::IsFastDoubleElementsKind(), v8::internal::IsFastElementsKind(), v8::internal::IsFastSmiElementsKind(), v8::internal::HGraphBuilder::isolate(), kFirstIndexOf, kLastIndexOf, mode(), NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), and v8::internal::Representation::Smi().

Referenced by TryInlineBuiltinMethodCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildBinaryOperation()

HValue * v8::internal::HOptimizedGraphBuilder::BuildBinaryOperation ( BinaryOperation *  expr,
HValue left,
HValue right,
PushBeforeSimulateBehavior  push_sim_result 
)
private

Definition at line 10224 of file hydrogen.cc.

10228  {
10229  Type* left_type = expr->left()->bounds().lower;
10230  Type* right_type = expr->right()->bounds().lower;
10231  Type* result_type = expr->bounds().lower;
10232  Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10233  Handle<AllocationSite> allocation_site = expr->allocation_site();
10234 
10235  HAllocationMode allocation_mode;
10236  if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
10237  allocation_mode = HAllocationMode(allocation_site);
10238  }
10239 
10240  HValue* result = HGraphBuilder::BuildBinaryOperation(
10241  expr->op(), left, right, left_type, right_type, result_type,
10242  fixed_right_arg, allocation_mode);
10243  // Add a simulate after instructions with observable side effects, and
10244  // after phis, which are the result of BuildBinaryOperation when we
10245  // inlined some complex subgraph.
10246  if (result->HasObservableSideEffects() || result->IsPhi()) {
10247  if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10248  Push(result);
10249  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10250  Drop(1);
10251  } else {
10252  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10253  }
10254  }
10255  return result;
10256 }
HValue * BuildBinaryOperation(Token::Value op, HValue *left, HValue *right, Type *left_type, Type *right_type, Type *result_type, Maybe< int > fixed_right_arg, HAllocationMode allocation_mode)
Definition: hydrogen.cc:10259
TypeImpl< ZoneTypeConfig > Type

References v8::internal::HGraphBuilder::BuildBinaryOperation(), Drop(), v8::internal::HValue::HasObservableSideEffects(), v8::internal::Handle< T >::is_null(), v8::internal::HValue::IsPhi(), v8::internal::HGraphBuilder::Push(), PUSH_BEFORE_SIMULATE, and v8::internal::REMOVABLE_SIMULATE.

Referenced by HandleCompoundAssignment(), and VisitArithmeticExpression().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildCallConstantFunction()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildCallConstantFunction ( Handle< JSFunction target,
int  argument_count 
)
private

Definition at line 7455 of file hydrogen.cc.

7456  {
7457  HValue* target = Add<HConstant>(jsfun);
7458  // For constant functions, we try to avoid calling the
7459  // argument adaptor and instead call the function directly
7460  int formal_parameter_count = jsfun->shared()->formal_parameter_count();
7461  bool dont_adapt_arguments =
7462  (formal_parameter_count ==
7464  int arity = argument_count - 1;
7465  bool can_invoke_directly =
7466  dont_adapt_arguments || formal_parameter_count == arity;
7467  if (can_invoke_directly) {
7468  if (jsfun.is_identical_to(current_info()->closure())) {
7469  graph()->MarkRecursive();
7470  }
7471  return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
7472  } else {
7473  HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7474  HValue* context = Add<HLoadNamedField>(
7475  target, static_cast<HValue*>(NULL),
7476  HObjectAccess::ForFunctionContextPointer());
7477  return NewArgumentAdaptorCall(target, context,
7478  argument_count, param_count_value);
7479  }
7480  UNREACHABLE();
7481  return NULL;
7482 }
HInstruction * NewArgumentAdaptorCall(HValue *fun, HValue *context, int argument_count, HValue *expected_param_count)
Definition: hydrogen.cc:7437
HInstruction * NewPlainFunctionCall(HValue *fun, int argument_count, bool pass_argument_count)
Definition: hydrogen.cc:7430
static const int kDontAdaptArgumentsSentinel
Definition: objects.h:6888
#define UNREACHABLE()
Definition: logging.h:30

References context(), current_info(), v8::internal::HGraphBuilder::graph(), v8::internal::SharedFunctionInfo::kDontAdaptArgumentsSentinel, NewArgumentAdaptorCall(), NewPlainFunctionCall(), NULL, and UNREACHABLE.

Referenced by BuildMonomorphicAccess(), and HandlePolymorphicCallNamed().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildCompareInstruction()

HControlInstruction * v8::internal::HOptimizedGraphBuilder::BuildCompareInstruction ( Token::Value  op,
HValue left,
HValue right,
Type left_type,
Type right_type,
Type combined_type,
HSourcePosition  left_position,
HSourcePosition  right_position,
PushBeforeSimulateBehavior  push_sim_result,
BailoutId  bailout_id 
)
private

Definition at line 10773 of file hydrogen.cc.

10783  {
10784  // Cases handled below depend on collected type feedback. They should
10785  // soft deoptimize when there is no type feedback.
10786  if (!combined_type->IsInhabited()) {
10787  Add<HDeoptimize>("Insufficient type feedback for combined type "
10788  "of binary operation",
10790  combined_type = left_type = right_type = Type::Any(zone());
10791  }
10792 
10793  Representation left_rep = Representation::FromType(left_type);
10794  Representation right_rep = Representation::FromType(right_type);
10795  Representation combined_rep = Representation::FromType(combined_type);
10796 
10797  if (combined_type->Is(Type::Receiver())) {
10798  if (Token::IsEqualityOp(op)) {
10799  // HCompareObjectEqAndBranch can only deal with object, so
10800  // exclude numbers.
10801  if ((left->IsConstant() &&
10802  HConstant::cast(left)->HasNumberValue()) ||
10803  (right->IsConstant() &&
10804  HConstant::cast(right)->HasNumberValue())) {
10805  Add<HDeoptimize>("Type mismatch between feedback and constant",
10807  // The caller expects a branch instruction, so make it happy.
10808  return New<HBranch>(graph()->GetConstantTrue());
10809  }
10810  // Can we get away with map check and not instance type check?
10811  HValue* operand_to_check =
10812  left->block()->block_id() < right->block()->block_id() ? left : right;
10813  if (combined_type->IsClass()) {
10814  Handle<Map> map = combined_type->AsClass()->Map();
10815  AddCheckMap(operand_to_check, map);
10816  HCompareObjectEqAndBranch* result =
10817  New<HCompareObjectEqAndBranch>(left, right);
10818  if (FLAG_hydrogen_track_positions) {
10819  result->set_operand_position(zone(), 0, left_position);
10820  result->set_operand_position(zone(), 1, right_position);
10821  }
10822  return result;
10823  } else {
10824  BuildCheckHeapObject(operand_to_check);
10825  Add<HCheckInstanceType>(operand_to_check,
10826  HCheckInstanceType::IS_SPEC_OBJECT);
10827  HCompareObjectEqAndBranch* result =
10828  New<HCompareObjectEqAndBranch>(left, right);
10829  return result;
10830  }
10831  } else {
10832  Bailout(kUnsupportedNonPrimitiveCompare);
10833  return NULL;
10834  }
10835  } else if (combined_type->Is(Type::InternalizedString()) &&
10836  Token::IsEqualityOp(op)) {
10837  // If we have a constant argument, it should be consistent with the type
10838  // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
10839  if ((left->IsConstant() &&
10840  !HConstant::cast(left)->HasInternalizedStringValue()) ||
10841  (right->IsConstant() &&
10842  !HConstant::cast(right)->HasInternalizedStringValue())) {
10843  Add<HDeoptimize>("Type mismatch between feedback and constant",
10845  // The caller expects a branch instruction, so make it happy.
10846  return New<HBranch>(graph()->GetConstantTrue());
10847  }
10848  BuildCheckHeapObject(left);
10849  Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
10850  BuildCheckHeapObject(right);
10851  Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
10852  HCompareObjectEqAndBranch* result =
10853  New<HCompareObjectEqAndBranch>(left, right);
10854  return result;
10855  } else if (combined_type->Is(Type::String())) {
10856  BuildCheckHeapObject(left);
10857  Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
10858  BuildCheckHeapObject(right);
10859  Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
10860  HStringCompareAndBranch* result =
10861  New<HStringCompareAndBranch>(left, right, op);
10862  return result;
10863  } else {
10864  if (combined_rep.IsTagged() || combined_rep.IsNone()) {
10865  HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
10866  result->set_observed_input_representation(1, left_rep);
10867  result->set_observed_input_representation(2, right_rep);
10868  if (result->HasObservableSideEffects()) {
10869  if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10870  Push(result);
10871  AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10872  Drop(1);
10873  } else {
10874  AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10875  }
10876  }
10877  // TODO(jkummerow): Can we make this more efficient?
10878  HBranch* branch = New<HBranch>(result);
10879  return branch;
10880  } else {
10881  HCompareNumericAndBranch* result =
10882  New<HCompareNumericAndBranch>(left, right, op);
10883  result->set_observed_input_representation(left_rep, right_rep);
10884  if (FLAG_hydrogen_track_positions) {
10885  result->SetOperandPositions(zone(), left_position, right_position);
10886  }
10887  return result;
10888  }
10889  }
10890 }
void AddSimulate(BailoutId id, RemovableSimulate removable=FIXED_SIMULATE)
Definition: hydrogen.cc:1232
HCheckMaps * AddCheckMap(HValue *object, Handle< Map > map)
Definition: hydrogen.cc:5797
void Bailout(BailoutReason reason)
Definition: hydrogen.cc:4212
static Representation FromType(Type *type)
static bool IsEqualityOp(Value op)
Definition: token.h:210

References AddCheckMap(), v8::internal::HGraphBuilder::AddSimulate(), v8::internal::TypeImpl< Config >::AsClass(), Bailout(), v8::internal::HValue::block(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), Drop(), v8::internal::Representation::FromType(), v8::internal::HGraphBuilder::graph(), v8::internal::TypeImpl< Config >::Is(), v8::internal::TypeImpl< Config >::IsClass(), v8::internal::Token::IsEqualityOp(), v8::internal::TypeImpl< Config >::IsInhabited(), v8::internal::Representation::IsNone(), v8::internal::Representation::IsTagged(), map, NULL, v8::internal::HGraphBuilder::Push(), PUSH_BEFORE_SIMULATE, v8::internal::REMOVABLE_SIMULATE, v8::internal::HCompareNumericAndBranch::set_observed_input_representation(), v8::internal::HInstruction::set_operand_position(), v8::internal::HCompareNumericAndBranch::SetOperandPositions(), v8::internal::Deoptimizer::SOFT, and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ BuildContextChainWalk()

HValue * v8::internal::HOptimizedGraphBuilder::BuildContextChainWalk ( Variable var)
private

Definition at line 5325 of file hydrogen.cc.

5325  {
5326  DCHECK(var->IsContextSlot());
5327  HValue* context = environment()->context();
5328  int length = scope()->ContextChainLength(var->scope());
5329  while (length-- > 0) {
5330  context = Add<HLoadNamedField>(
5331  context, static_cast<HValue*>(NULL),
5332  HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5333  }
5334  return context;
5335 }
Scope * scope() const
Definition: hydrogen.h:1054
int ContextChainLength(Scope *scope)
Definition: scopes.cc:715

References context(), v8::internal::Scope::ContextChainLength(), DCHECK, v8::internal::HGraphBuilder::environment(), v8::internal::Variable::IsContextSlot(), NULL, v8::internal::Context::PREVIOUS_INDEX, v8::internal::HGraphBuilder::scope(), and v8::internal::Variable::scope().

Referenced by HandleCompoundAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildEmitElements()

void v8::internal::HOptimizedGraphBuilder::BuildEmitElements ( Handle< JSObject boilerplate_object,
Handle< FixedArrayBase elements,
HValue object_elements,
AllocationSiteUsageContext site_context 
)
private

Definition at line 11137 of file hydrogen.cc.

11141  {
11142  ElementsKind kind = boilerplate_object->map()->elements_kind();
11143  int elements_length = elements->length();
11144  HValue* object_elements_length = Add<HConstant>(elements_length);
11145  BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
11146 
11147  // Copy elements backing store content.
11148  if (elements->IsFixedDoubleArray()) {
11149  BuildEmitFixedDoubleArray(elements, kind, object_elements);
11150  } else if (elements->IsFixedArray()) {
11151  BuildEmitFixedArray(elements, kind, object_elements,
11152  site_context);
11153  } else {
11154  UNREACHABLE();
11155  }
11156 }
void BuildInitializeElementsHeader(HValue *elements, ElementsKind kind, HValue *capacity)
Definition: hydrogen.cc:2615
void BuildEmitFixedArray(Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements, AllocationSiteUsageContext *site_context)
Definition: hydrogen.cc:11178
void BuildEmitFixedDoubleArray(Handle< FixedArrayBase > elements, ElementsKind kind, HValue *object_elements)
Definition: hydrogen.cc:11159

References BuildEmitFixedArray(), BuildEmitFixedDoubleArray(), v8::internal::HGraphBuilder::BuildInitializeElementsHeader(), and UNREACHABLE.

Referenced by BuildFastLiteral().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildEmitFixedArray()

void v8::internal::HOptimizedGraphBuilder::BuildEmitFixedArray ( Handle< FixedArrayBase elements,
ElementsKind  kind,
HValue object_elements,
AllocationSiteUsageContext site_context 
)
private

Definition at line 11178 of file hydrogen.cc.

11182  {
11183  HInstruction* boilerplate_elements = Add<HConstant>(elements);
11184  int elements_length = elements->length();
11185  Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
11186  for (int i = 0; i < elements_length; i++) {
11187  Handle<Object> value(fast_elements->get(i), isolate());
11188  HValue* key_constant = Add<HConstant>(i);
11189  if (value->IsJSObject()) {
11190  Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11191  Handle<AllocationSite> current_site = site_context->EnterNewScope();
11192  HInstruction* result =
11193  BuildFastLiteral(value_object, site_context);
11194  site_context->ExitScope(current_site, value_object);
11195  Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11196  } else {
11197  HInstruction* value_instruction =
11198  Add<HLoadKeyed>(boilerplate_elements, key_constant,
11199  static_cast<HValue*>(NULL), kind,
11201  Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
11202  }
11203  }
11204 }
HInstruction * BuildFastLiteral(Handle< JSObject > boilerplate_object, AllocationSiteUsageContext *site_context)
Definition: hydrogen.cc:10933
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116

References v8::internal::ALLOW_RETURN_HOLE, BuildFastLiteral(), v8::internal::Handle< T >::cast(), v8::internal::AllocationSiteUsageContext::EnterNewScope(), v8::internal::AllocationSiteUsageContext::ExitScope(), v8::internal::HGraphBuilder::isolate(), and NULL.

Referenced by BuildEmitElements().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildEmitFixedDoubleArray()

void v8::internal::HOptimizedGraphBuilder::BuildEmitFixedDoubleArray ( Handle< FixedArrayBase elements,
ElementsKind  kind,
HValue object_elements 
)
private

Definition at line 11159 of file hydrogen.cc.

11162  {
11163  HInstruction* boilerplate_elements = Add<HConstant>(elements);
11164  int elements_length = elements->length();
11165  for (int i = 0; i < elements_length; i++) {
11166  HValue* key_constant = Add<HConstant>(i);
11167  HInstruction* value_instruction =
11168  Add<HLoadKeyed>(boilerplate_elements, key_constant,
11169  static_cast<HValue*>(NULL), kind,
11171  HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11172  value_instruction, kind);
11173  store->SetFlag(HValue::kAllowUndefinedAsNaN);
11174  }
11175 }

References v8::internal::ALLOW_RETURN_HOLE, v8::internal::HValue::kAllowUndefinedAsNaN, NULL, and v8::internal::HValue::SetFlag().

Referenced by BuildEmitElements().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildEmitInObjectProperties()

void v8::internal::HOptimizedGraphBuilder::BuildEmitInObjectProperties ( Handle< JSObject boilerplate_object,
HInstruction object,
AllocationSiteUsageContext site_context,
PretenureFlag  pretenure_flag 
)
private

Definition at line 11055 of file hydrogen.cc.

11059  {
11060  Handle<Map> boilerplate_map(boilerplate_object->map());
11061  Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
11062  int limit = boilerplate_map->NumberOfOwnDescriptors();
11063 
11064  int copied_fields = 0;
11065  for (int i = 0; i < limit; i++) {
11066  PropertyDetails details = descriptors->GetDetails(i);
11067  if (details.type() != FIELD) continue;
11068  copied_fields++;
11069  int index = descriptors->GetFieldIndex(i);
11070  int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
11071  Handle<Name> name(descriptors->GetKey(i));
11072  Handle<Object> value =
11073  Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
11074  isolate());
11075 
11076  // The access for the store depends on the type of the boilerplate.
11077  HObjectAccess access = boilerplate_object->IsJSArray() ?
11078  HObjectAccess::ForJSArrayOffset(property_offset) :
11079  HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11080 
11081  if (value->IsJSObject()) {
11082  Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11083  Handle<AllocationSite> current_site = site_context->EnterNewScope();
11084  HInstruction* result =
11085  BuildFastLiteral(value_object, site_context);
11086  site_context->ExitScope(current_site, value_object);
11087  Add<HStoreNamedField>(object, access, result);
11088  } else {
11089  Representation representation = details.representation();
11090  HInstruction* value_instruction;
11091 
11092  if (representation.IsDouble()) {
11093  // Allocate a HeapNumber box and store the value into it.
11094  HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
11095  // This heap number alloc does not have a corresponding
11096  // AllocationSite. That is okay because
11097  // 1) it's a child object of another object with a valid allocation site
11098  // 2) we can just use the mode of the parent object for pretenuring
11099  HInstruction* double_box =
11100  Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11101  pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
11102  AddStoreMapConstant(double_box,
11103  isolate()->factory()->mutable_heap_number_map());
11104  // Unwrap the mutable heap number from the boilerplate.
11105  HValue* double_value =
11106  Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
11107  Add<HStoreNamedField>(
11108  double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11109  value_instruction = double_box;
11110  } else if (representation.IsSmi()) {
11111  value_instruction = value->IsUninitialized()
11112  ? graph()->GetConstant0()
11113  : Add<HConstant>(value);
11114  // Ensure that value is stored as smi.
11115  access = access.WithRepresentation(representation);
11116  } else {
11117  value_instruction = Add<HConstant>(value);
11118  }
11119 
11120  Add<HStoreNamedField>(object, access, value_instruction);
11121  }
11122  }
11123 
11124  int inobject_properties = boilerplate_object->map()->inobject_properties();
11125  HInstruction* value_instruction =
11126  Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
11127  for (int i = copied_fields; i < inobject_properties; i++) {
11128  DCHECK(boilerplate_object->IsJSObject());
11129  int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
11130  HObjectAccess access =
11131  HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11132  Add<HStoreNamedField>(object, access, value_instruction);
11133  }
11134 }
static const int kSize
Definition: objects.h:1521
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
@ MUTABLE_HEAP_NUMBER_TYPE
Definition: objects.h:670

References v8::internal::HGraphBuilder::AddStoreMapConstant(), BuildFastLiteral(), v8::internal::Handle< T >::cast(), DCHECK, v8::internal::AllocationSiteUsageContext::EnterNewScope(), v8::internal::AllocationSiteUsageContext::ExitScope(), v8::internal::FIELD, v8::internal::HGraphBuilder::graph(), v8::internal::Representation::IsDouble(), v8::internal::HGraphBuilder::isolate(), v8::internal::Representation::IsSmi(), v8::internal::HeapNumber::kSize, v8::internal::MUTABLE_HEAP_NUMBER_TYPE, and name.

Referenced by BuildFastLiteral().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildEmitObjectHeader()

void v8::internal::HOptimizedGraphBuilder::BuildEmitObjectHeader ( Handle< JSObject boilerplate_object,
HInstruction object 
)
private

Definition at line 11011 of file hydrogen.cc.

11013  {
11014  DCHECK(boilerplate_object->properties()->length() == 0);
11015 
11016  Handle<Map> boilerplate_object_map(boilerplate_object->map());
11017  AddStoreMapConstant(object, boilerplate_object_map);
11018 
11019  Handle<Object> properties_field =
11020  Handle<Object>(boilerplate_object->properties(), isolate());
11021  DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
11022  HInstruction* properties = Add<HConstant>(properties_field);
11023  HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11024  Add<HStoreNamedField>(object, access, properties);
11025 
11026  if (boilerplate_object->IsJSArray()) {
11027  Handle<JSArray> boilerplate_array =
11028  Handle<JSArray>::cast(boilerplate_object);
11029  Handle<Object> length_field =
11030  Handle<Object>(boilerplate_array->length(), isolate());
11031  HInstruction* length = Add<HConstant>(length_field);
11032 
11033  DCHECK(boilerplate_array->length()->IsSmi());
11034  Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
11035  boilerplate_array->GetElementsKind()), length);
11036  }
11037 }

References v8::internal::HGraphBuilder::AddStoreMapConstant(), v8::internal::Handle< T >::cast(), DCHECK, and v8::internal::HGraphBuilder::isolate().

Referenced by BuildFastLiteral().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildFastLiteral()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildFastLiteral ( Handle< JSObject boilerplate_object,
AllocationSiteUsageContext site_context 
)
private

Definition at line 10933 of file hydrogen.cc.

10935  {
10936  NoObservableSideEffectsScope no_effects(this);
10937  InstanceType instance_type = boilerplate_object->map()->instance_type();
10938  DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
10939 
10940  HType type = instance_type == JS_ARRAY_TYPE
10941  ? HType::JSArray() : HType::JSObject();
10942  HValue* object_size_constant = Add<HConstant>(
10943  boilerplate_object->map()->instance_size());
10944 
10945  PretenureFlag pretenure_flag = NOT_TENURED;
10946  if (FLAG_allocation_site_pretenuring) {
10947  pretenure_flag = site_context->current()->GetPretenureMode();
10948  Handle<AllocationSite> site(site_context->current());
10951  }
10952 
10953  HInstruction* object = Add<HAllocate>(object_size_constant, type,
10954  pretenure_flag, instance_type, site_context->current());
10955 
10956  // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
10957  // elements array may not get folded into the object. Hence, we set the
10958  // elements pointer to empty fixed array and let store elimination remove
10959  // this store in the folding case.
10960  HConstant* empty_fixed_array = Add<HConstant>(
10961  isolate()->factory()->empty_fixed_array());
10962  Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
10963  empty_fixed_array);
10964 
10965  BuildEmitObjectHeader(boilerplate_object, object);
10966 
10967  Handle<FixedArrayBase> elements(boilerplate_object->elements());
10968  int elements_size = (elements->length() > 0 &&
10969  elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
10970  elements->Size() : 0;
10971 
10972  if (pretenure_flag == TENURED &&
10973  elements->map() == isolate()->heap()->fixed_cow_array_map() &&
10974  isolate()->heap()->InNewSpace(*elements)) {
10975  // If we would like to pretenure a fixed cow array, we must ensure that the
10976  // array is already in old space, otherwise we'll create too many old-to-
10977  // new-space pointers (overflowing the store buffer).
10978  elements = Handle<FixedArrayBase>(
10979  isolate()->factory()->CopyAndTenureFixedCOWArray(
10980  Handle<FixedArray>::cast(elements)));
10981  boilerplate_object->set_elements(*elements);
10982  }
10983 
10984  HInstruction* object_elements = NULL;
10985  if (elements_size > 0) {
10986  HValue* object_elements_size = Add<HConstant>(elements_size);
10987  InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
10989  object_elements = Add<HAllocate>(
10990  object_elements_size, HType::HeapObject(),
10991  pretenure_flag, instance_type, site_context->current());
10992  }
10993  BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
10994 
10995  // Copy object elements if non-COW.
10996  if (object_elements != NULL) {
10997  BuildEmitElements(boilerplate_object, elements, object_elements,
10998  site_context);
10999  }
11000 
11001  // Copy in-object properties.
11002  if (boilerplate_object->map()->NumberOfFields() != 0 ||
11003  boilerplate_object->map()->unused_property_fields() > 0) {
11004  BuildEmitInObjectProperties(boilerplate_object, object, site_context,
11005  pretenure_flag);
11006  }
11007  return object;
11008 }
static void AddDependentCompilationInfo(Handle< AllocationSite > site, Reason reason, CompilationInfo *info)
Definition: objects.cc:12660
CompilationInfo * top_info()
Definition: hydrogen.h:1065
void BuildInitElementsInObjectHeader(Handle< JSObject > boilerplate_object, HInstruction *object, HInstruction *object_elements)
Definition: hydrogen.cc:11040
void BuildEmitInObjectProperties(Handle< JSObject > boilerplate_object, HInstruction *object, AllocationSiteUsageContext *site_context, PretenureFlag pretenure_flag)
Definition: hydrogen.cc:11055
void BuildEmitElements(Handle< JSObject > boilerplate_object, Handle< FixedArrayBase > elements, HValue *object_elements, AllocationSiteUsageContext *site_context)
Definition: hydrogen.cc:11137
void BuildEmitObjectHeader(Handle< JSObject > boilerplate_object, HInstruction *object)
Definition: hydrogen.cc:11011
bool InNewSpace(Object *object)
Definition: heap-inl.h:322
@ FIXED_DOUBLE_ARRAY_TYPE
Definition: objects.h:692
@ JS_ARRAY_TYPE
Definition: objects.h:738
@ FIXED_ARRAY_TYPE
Definition: objects.h:717
@ JS_OBJECT_TYPE
Definition: objects.h:731

References v8::internal::AllocationSite::AddDependentCompilationInfo(), BuildEmitElements(), BuildEmitInObjectProperties(), BuildEmitObjectHeader(), BuildInitElementsInObjectHeader(), v8::internal::AllocationSiteContext::current(), DCHECK, v8::internal::FIXED_ARRAY_TYPE, v8::internal::FIXED_DOUBLE_ARRAY_TYPE, v8::internal::Isolate::heap(), v8::internal::Heap::InNewSpace(), v8::internal::HGraphBuilder::isolate(), v8::internal::JS_ARRAY_TYPE, v8::internal::JS_OBJECT_TYPE, v8::internal::NOT_TENURED, NULL, v8::internal::TENURED, v8::internal::AllocationSite::TENURING, and v8::internal::HGraphBuilder::top_info().

Referenced by BuildEmitFixedArray(), and BuildEmitInObjectProperties().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildGraph()

bool v8::internal::HOptimizedGraphBuilder::BuildGraph ( )
virtual

Implements v8::internal::HGraphBuilder.

Definition at line 4254 of file hydrogen.cc.

4254  {
4255  if (current_info()->function()->is_generator()) {
4256  Bailout(kFunctionIsAGenerator);
4257  return false;
4258  }
4259  Scope* scope = current_info()->scope();
4260  if (scope->HasIllegalRedeclaration()) {
4261  Bailout(kFunctionWithIllegalRedeclaration);
4262  return false;
4263  }
4264  if (scope->calls_eval()) {
4265  Bailout(kFunctionCallsEval);
4266  return false;
4267  }
4268  SetUpScope(scope);
4269 
4270  // Add an edge to the body entry. This is warty: the graph's start
4271  // environment will be used by the Lithium translation as the initial
4272  // environment on graph entry, but it has now been mutated by the
4273  // Hydrogen translation of the instructions in the start block. This
4274  // environment uses values which have not been defined yet. These
4275  // Hydrogen instructions will then be replayed by the Lithium
4276  // translation, so they cannot have an environment effect. The edge to
4277  // the body's entry block (along with some special logic for the start
4278  // block in HInstruction::InsertAfter) seals the start block from
4279  // getting unwanted instructions inserted.
4280  //
4281  // TODO(kmillikin): Fix this. Stop mutating the initial environment.
4282  // Make the Hydrogen instructions in the initial block into Hydrogen
4283  // values (but not instructions), present in the initial environment and
4284  // not replayed by the Lithium translation.
4285  HEnvironment* initial_env = environment()->CopyWithoutHistory();
4286  HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4287  Goto(body_entry);
4288  body_entry->SetJoinId(BailoutId::FunctionEntry());
4289  set_current_block(body_entry);
4290 
4291  // Handle implicit declaration of the function name in named function
4292  // expressions before other declarations.
4293  if (scope->is_function_scope() && scope->function() != NULL) {
4294  VisitVariableDeclaration(scope->function());
4295  }
4297  Add<HSimulate>(BailoutId::Declarations());
4298 
4299  Add<HStackCheck>(HStackCheck::kFunctionEntry);
4300 
4301  VisitStatements(current_info()->function()->body());
4302  if (HasStackOverflow()) return false;
4303 
4304  if (current_block() != NULL) {
4305  Add<HReturn>(graph()->GetConstantUndefined());
4307  }
4308 
4309  // If the checksum of the number of type info changes is the same as the
4310  // last time this function was compiled, then this recompile is likely not
4311  // due to missing/inadequate type feedback, but rather too aggressive
4312  // optimization. Disable optimistic LICM in that case.
4313  Handle<Code> unoptimized_code(current_info()->shared_info()->code());
4314  DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4315  Handle<TypeFeedbackInfo> type_info(
4316  TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4317  int checksum = type_info->own_type_change_checksum();
4318  int composite_checksum = graph()->update_type_change_checksum(checksum);
4319  graph()->set_use_optimistic_licm(
4320  !type_info->matches_inlined_type_change_checksum(composite_checksum));
4321  type_info->set_inlined_type_change_checksum(composite_checksum);
4322 
4323  // Perform any necessary OSR-specific cleanups or changes to the graph.
4324  osr()->FinishGraph();
4325 
4326  return true;
4327 }
static BailoutId Declarations()
Definition: utils.h:962
static BailoutId FunctionEntry()
Definition: utils.h:961
void set_current_block(HBasicBlock *block)
Definition: hydrogen.h:1058
void Goto(HBasicBlock *from, HBasicBlock *target, FunctionState *state=NULL, bool add_simulate=true)
Definition: hydrogen.h:1080
HBasicBlock * CreateBasicBlock(HEnvironment *env)
Definition: hydrogen.cc:1240
HBasicBlock * current_block() const
Definition: hydrogen.h:1057
virtual void VisitStatements(ZoneList< Statement * > *statements) OVERRIDE
Definition: hydrogen.cc:4518
void VisitDeclarations(ZoneList< Declaration * > *declarations)
Definition: hydrogen.cc:11224
VariableDeclaration * function() const
Definition: scopes.h:309
bool calls_eval() const
Definition: scopes.h:280
bool HasIllegalRedeclaration() const
Definition: scopes.h:198
bool is_function_scope() const
Definition: scopes.h:265
ZoneList< Declaration * > * declarations()
Definition: scopes.h:327

References Bailout(), v8::internal::Scope::calls_eval(), v8::internal::HGraphBuilder::CreateBasicBlock(), v8::internal::HGraphBuilder::current_block(), current_info(), DCHECK, v8::internal::Scope::declarations(), v8::internal::BailoutId::Declarations(), v8::internal::HGraphBuilder::environment(), v8::internal::HOsrBuilder::FinishGraph(), v8::internal::Scope::function(), v8::internal::BailoutId::FunctionEntry(), v8::internal::HGraphBuilder::Goto(), v8::internal::HGraphBuilder::graph(), v8::internal::Scope::HasIllegalRedeclaration(), v8::internal::Scope::is_function_scope(), NULL, osr(), v8::internal::CompilationInfo::scope(), v8::internal::HGraphBuilder::scope(), v8::internal::HGraphBuilder::set_current_block(), SetUpScope(), VisitDeclarations(), and VisitStatements().

+ Here is the call graph for this function:

◆ BuildIncrement()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildIncrement ( bool  returns_original_input,
CountOperation *  expr 
)
private

Definition at line 9924 of file hydrogen.cc.

9926  {
9927  // The input to the count operation is on top of the expression stack.
9928  Representation rep = Representation::FromType(expr->type());
9929  if (rep.IsNone() || rep.IsTagged()) {
9930  rep = Representation::Smi();
9931  }
9932 
9933  if (returns_original_input) {
9934  // We need an explicit HValue representing ToNumber(input). The
9935  // actual HChange instruction we need is (sometimes) added in a later
9936  // phase, so it is not available now to be used as an input to HAdd and
9937  // as the return value.
9938  HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
9939  if (!rep.IsDouble()) {
9940  number_input->SetFlag(HInstruction::kFlexibleRepresentation);
9941  number_input->SetFlag(HInstruction::kCannotBeTagged);
9942  }
9943  Push(number_input);
9944  }
9945 
9946  // The addition has no side effects, so we do not need
9947  // to simulate the expression stack after this instruction.
9948  // Any later failures deopt to the load of the input or earlier.
9949  HConstant* delta = (expr->op() == Token::INC)
9950  ? graph()->GetConstant1()
9951  : graph()->GetConstantMinus1();
9952  HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
9953  if (instr->IsAdd()) {
9954  HAdd* add = HAdd::cast(instr);
9955  add->set_observed_input_representation(1, rep);
9956  add->set_observed_input_representation(2, Representation::Smi());
9957  }
9958  instr->SetFlag(HInstruction::kCannotBeTagged);
9959  instr->ClearAllSideEffects();
9960  return instr;
9961 }

References v8::internal::HValue::ClearAllSideEffects(), v8::internal::Representation::FromType(), v8::internal::HGraphBuilder::graph(), v8::internal::Representation::IsDouble(), v8::internal::Representation::IsNone(), v8::internal::Representation::IsTagged(), v8::internal::HValue::kCannotBeTagged, v8::internal::HValue::kFlexibleRepresentation, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::HValue::SetFlag(), v8::internal::Representation::Smi(), and Top().

+ Here is the call graph for this function:

◆ BuildInitElementsInObjectHeader()

void v8::internal::HOptimizedGraphBuilder::BuildInitElementsInObjectHeader ( Handle< JSObject boilerplate_object,
HInstruction object,
HInstruction object_elements 
)
private

Definition at line 11040 of file hydrogen.cc.

11043  {
11044  DCHECK(boilerplate_object->properties()->length() == 0);
11045  if (object_elements == NULL) {
11046  Handle<Object> elements_field =
11047  Handle<Object>(boilerplate_object->elements(), isolate());
11048  object_elements = Add<HConstant>(elements_field);
11049  }
11050  Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11051  object_elements);
11052 }

References DCHECK, v8::internal::HGraphBuilder::isolate(), and NULL.

Referenced by BuildFastLiteral().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildInlinedCallArray()

void v8::internal::HOptimizedGraphBuilder::BuildInlinedCallArray ( Expression expression,
int  argument_count,
Handle< AllocationSite site 
)
private

Definition at line 9161 of file hydrogen.cc.

9164  {
9165  DCHECK(!site.is_null());
9166  DCHECK(argument_count >= 0 && argument_count <= 1);
9167  NoObservableSideEffectsScope no_effects(this);
9168 
9169  // We should at least have the constructor on the expression stack.
9170  HValue* constructor = environment()->ExpressionStackAt(argument_count);
9171 
9172  // Register on the site for deoptimization if the transition feedback changes.
9175  ElementsKind kind = site->GetElementsKind();
9176  HInstruction* site_instruction = Add<HConstant>(site);
9177 
9178  // In the single constant argument case, we may have to adjust elements kind
9179  // to avoid creating a packed non-empty array.
9180  if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
9181  HValue* argument = environment()->Top();
9182  if (argument->IsConstant()) {
9183  HConstant* constant_argument = HConstant::cast(argument);
9184  DCHECK(constant_argument->HasSmiValue());
9185  int constant_array_size = constant_argument->Integer32Value();
9186  if (constant_array_size != 0) {
9187  kind = GetHoleyElementsKind(kind);
9188  }
9189  }
9190  }
9191 
9192  // Build the array.
9193  JSArrayBuilder array_builder(this,
9194  kind,
9195  site_instruction,
9196  constructor,
9198  HValue* new_object = argument_count == 0
9199  ? array_builder.AllocateEmptyArray()
9200  : BuildAllocateArrayFromLength(&array_builder, Top());
9201 
9202  int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9203  Drop(args_to_drop);
9204  ast_context()->ReturnValue(new_object);
9205 }
virtual void ReturnValue(HValue *value)=0
HValue * BuildAllocateArrayFromLength(JSArrayBuilder *array_builder, HValue *length_argument)
Definition: hydrogen.cc:2514
bool IsHoleyElementsKind(ElementsKind kind)
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
@ DISABLE_ALLOCATION_SITES
Definition: code-stubs.h:718

References v8::internal::AllocationSite::AddDependentCompilationInfo(), ast_context(), v8::internal::HGraphBuilder::BuildAllocateArrayFromLength(), DCHECK, v8::internal::DISABLE_ALLOCATION_SITES, Drop(), v8::internal::HGraphBuilder::environment(), v8::internal::GetHoleyElementsKind(), v8::internal::Handle< T >::is_null(), v8::internal::IsHoleyElementsKind(), v8::internal::AstContext::ReturnValue(), Top(), v8::internal::HGraphBuilder::top_info(), and v8::internal::AllocationSite::TRANSITIONS.

Referenced by BuildArrayCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildKeyedGeneric()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildKeyedGeneric ( PropertyAccessType  access_type,
Expression expr,
HValue object,
HValue key,
HValue value 
)
private

Definition at line 6847 of file hydrogen.cc.

6852  {
6853  if (access_type == LOAD) {
6854  HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(object, key);
6855  if (FLAG_vector_ics) {
6856  Handle<SharedFunctionInfo> current_shared =
6857  function_state()->compilation_info()->shared_info();
6858  result->SetVectorAndSlot(
6859  handle(current_shared->feedback_vector(), isolate()),
6860  expr->AsProperty()->PropertyFeedbackSlot());
6861  }
6862  return result;
6863  } else {
6864  return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode());
6865  }
6866 }
FunctionState * function_state() const
Definition: hydrogen.h:2123

References function_state(), function_strict_mode(), v8::internal::handle(), v8::internal::HGraphBuilder::isolate(), and v8::internal::LOAD.

Referenced by HandleKeyedElementAccess(), and HandlePolymorphicElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildKeyedHoleMode()

LoadKeyedHoleMode v8::internal::HOptimizedGraphBuilder::BuildKeyedHoleMode ( Handle< Map map)
private

Definition at line 6869 of file hydrogen.cc.

6869  {
6870  // Loads from a "stock" fast holey double arrays can elide the hole check.
6872  if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
6873  isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6874  Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
6875  Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
6876  BuildCheckPrototypeMaps(prototype, object_prototype);
6877  load_mode = ALLOW_RETURN_HOLE;
6878  graph()->MarkDependsOnEmptyArrayProtoElements();
6879  }
6880 
6881  return load_mode;
6882 }
@ FAST_HOLEY_DOUBLE_ELEMENTS
Definition: elements-kind.h:27

References v8::internal::ALLOW_RETURN_HOLE, v8::internal::HGraphBuilder::BuildCheckPrototypeMaps(), v8::internal::FAST_HOLEY_DOUBLE_ELEMENTS, v8::internal::HGraphBuilder::graph(), v8::internal::HGraphBuilder::isolate(), map, and v8::internal::NEVER_RETURN_HOLE.

Referenced by BuildMonomorphicElementAccess(), and HandlePolymorphicElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildLoad()

void v8::internal::HOptimizedGraphBuilder::BuildLoad ( Property *  property,
BailoutId  ast_id 
)
private

Definition at line 7337 of file hydrogen.cc.

7338  {
7339  HInstruction* instr = NULL;
7340  if (expr->IsStringAccess()) {
7341  HValue* index = Pop();
7342  HValue* string = Pop();
7343  HInstruction* char_code = BuildStringCharCodeAt(string, index);
7344  AddInstruction(char_code);
7345  instr = NewUncasted<HStringCharFromCode>(char_code);
7346 
7347  } else if (expr->key()->IsPropertyName()) {
7348  Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7349  HValue* object = Pop();
7350 
7351  instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7352  object, name, NULL, expr->IsUninitialized());
7353  if (instr == NULL) return;
7354  if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7355 
7356  } else {
7357  HValue* key = Pop();
7358  HValue* obj = Pop();
7359 
7360  bool has_side_effects = false;
7361  HValue* load = HandleKeyedElementAccess(
7362  obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects);
7363  if (has_side_effects) {
7364  if (ast_context()->IsEffect()) {
7365  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7366  } else {
7367  Push(load);
7368  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7369  Drop(1);
7370  }
7371  }
7372  if (load == NULL) return;
7373  return ast_context()->ReturnValue(load);
7374  }
7375  return ast_context()->ReturnInstruction(instr, ast_id);
7376 }
HInstruction * AddInstruction(HInstruction *instr)
Definition: hydrogen.cc:1185
HInstruction * BuildNamedAccess(PropertyAccessType access, BailoutId ast_id, BailoutId reutrn_id, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
Definition: hydrogen.cc:7288
HInstruction * BuildStringCharCodeAt(HValue *string, HValue *index)
Definition: hydrogen.cc:10091
HValue * HandleKeyedElementAccess(HValue *obj, HValue *key, HValue *val, Expression *expr, BailoutId ast_id, BailoutId return_id, PropertyAccessType access_type, bool *has_side_effects)
Definition: hydrogen.cc:7125

References v8::internal::HGraphBuilder::AddInstruction(), ast_context(), BuildNamedAccess(), BuildStringCharCodeAt(), Drop(), HandleKeyedElementAccess(), v8::internal::HInstruction::IsLinked(), v8::internal::LOAD, name, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnInstruction(), and v8::internal::AstContext::ReturnValue().

Referenced by PushLoad().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildLoadNamedField()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildLoadNamedField ( PropertyAccessInfo info,
HValue checked_object 
)
private

Definition at line 5804 of file hydrogen.cc.

5806  {
5807  // See if this is a load for an immutable property
5808  if (checked_object->ActualValue()->IsConstant()) {
5809  Handle<Object> object(
5810  HConstant::cast(checked_object->ActualValue())->handle(isolate()));
5811 
5812  if (object->IsJSObject()) {
5813  LookupIterator it(object, info->name(),
5814  LookupIterator::OWN_SKIP_INTERCEPTOR);
5815  Handle<Object> value = JSObject::GetDataProperty(&it);
5816  if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
5817  return New<HConstant>(value);
5818  }
5819  }
5820  }
5821 
5822  HObjectAccess access = info->access();
5823  if (access.representation().IsDouble()) {
5824  // Load the heap number.
5825  checked_object = Add<HLoadNamedField>(
5826  checked_object, static_cast<HValue*>(NULL),
5827  access.WithRepresentation(Representation::Tagged()));
5828  // Load the double value from it.
5829  access = HObjectAccess::ForHeapNumberValue();
5830  }
5831 
5832  SmallMapList* map_list = info->field_maps();
5833  if (map_list->length() == 0) {
5834  return New<HLoadNamedField>(checked_object, checked_object, access);
5835  }
5836 
5837  UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
5838  for (int i = 0; i < map_list->length(); ++i) {
5839  maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
5840  }
5841  return New<HLoadNamedField>(
5842  checked_object, checked_object, access, maps, info->field_type());
5843 }
static Handle< Object > GetDataProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:140
static Representation Tagged()
static Unique< T > CreateImmovable(Handle< T > handle)
Definition: unique.h:116

References v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::access(), v8::internal::HValue::ActualValue(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::field_maps(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::field_type(), v8::internal::JSObject::GetDataProperty(), v8::internal::HGraphBuilder::isolate(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::name(), NULL, v8::internal::Representation::Tagged(), and v8::internal::HGraphBuilder::zone().

Referenced by BuildMonomorphicAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildLoopEntry() [1/2]

HBasicBlock * v8::internal::HOptimizedGraphBuilder::BuildLoopEntry ( )
protected

Definition at line 3387 of file hydrogen.cc.

3387  {
3388  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3389  Goto(loop_entry);
3390  set_current_block(loop_entry);
3391  return loop_entry;
3392 }
HBasicBlock * CreateLoopHeaderBlock()
Definition: hydrogen.cc:1247

References v8::internal::HGraphBuilder::CreateLoopHeaderBlock(), v8::internal::HGraphBuilder::Goto(), and v8::internal::HGraphBuilder::set_current_block().

Referenced by BuildLoopEntry(), and v8::internal::HOsrBuilder::BuildOsrLoopEntry().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildLoopEntry() [2/2]

HBasicBlock * v8::internal::HOptimizedGraphBuilder::BuildLoopEntry ( IterationStatement statement)
protected

Definition at line 3395 of file hydrogen.cc.

3396  {
3397  HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3398  ? osr()->BuildOsrLoopEntry(statement)
3399  : BuildLoopEntry();
3400  return loop_entry;
3401 }
HBasicBlock * BuildOsrLoopEntry(IterationStatement *statement)
Definition: hydrogen-osr.cc:17
bool HasOsrEntryAt(IterationStatement *statement)
Definition: hydrogen-osr.cc:12

References BuildLoopEntry(), v8::internal::HOsrBuilder::BuildOsrLoopEntry(), v8::internal::HOsrBuilder::HasOsrEntryAt(), and osr().

+ Here is the call graph for this function:

◆ BuildMonomorphicAccess()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildMonomorphicAccess ( PropertyAccessInfo info,
HValue object,
HValue checked_object,
HValue value,
BailoutId  ast_id,
BailoutId  return_id,
bool  can_inline_accessor = true 
)
private

Definition at line 6172 of file hydrogen.cc.

6179  {
6180 
6181  HObjectAccess access = HObjectAccess::ForMap(); // bogus default
6182  if (info->GetJSObjectFieldAccess(&access)) {
6183  DCHECK(info->IsLoad());
6184  return New<HLoadNamedField>(object, checked_object, access);
6185  }
6186 
6187  if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
6188  info->map()->function_with_prototype()) {
6189  DCHECK(!info->map()->has_non_instance_prototype());
6190  return New<HLoadFunctionPrototype>(checked_object);
6191  }
6192 
6193  HValue* checked_holder = checked_object;
6194  if (info->has_holder()) {
6195  Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
6196  checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
6197  }
6198 
6199  if (!info->IsFound()) {
6200  DCHECK(info->IsLoad());
6201  return graph()->GetConstantUndefined();
6202  }
6203 
6204  if (info->IsField()) {
6205  if (info->IsLoad()) {
6206  return BuildLoadNamedField(info, checked_holder);
6207  } else {
6208  return BuildStoreNamedField(info, checked_object, value);
6209  }
6210  }
6211 
6212  if (info->IsTransition()) {
6213  DCHECK(!info->IsLoad());
6214  return BuildStoreNamedField(info, checked_object, value);
6215  }
6216 
6217  if (info->IsAccessor()) {
6218  Push(checked_object);
6219  int argument_count = 1;
6220  if (!info->IsLoad()) {
6221  argument_count = 2;
6222  Push(value);
6223  }
6224 
6225  if (NeedsWrappingFor(info->type(), info->accessor())) {
6226  HValue* function = Add<HConstant>(info->accessor());
6227  PushArgumentsFromEnvironment(argument_count);
6228  return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
6229  } else if (FLAG_inline_accessors && can_inline_accessor) {
6230  bool success = info->IsLoad()
6231  ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
6232  : TryInlineSetter(
6233  info->accessor(), info->map(), ast_id, return_id, value);
6234  if (success || HasStackOverflow()) return NULL;
6235  }
6236 
6237  PushArgumentsFromEnvironment(argument_count);
6238  return BuildCallConstantFunction(info->accessor(), argument_count);
6239  }
6240 
6241  DCHECK(info->IsConstant());
6242  if (info->IsLoad()) {
6243  return New<HConstant>(info->constant());
6244  } else {
6245  return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6246  }
6247 }
HInstruction * BuildCallConstantFunction(Handle< JSFunction > target, int argument_count)
Definition: hydrogen.cc:7455
void PushArgumentsFromEnvironment(int count)
Definition: hydrogen.cc:4453
bool TryInlineSetter(Handle< JSFunction > setter, Handle< Map > receiver_map, BailoutId id, BailoutId assignment_id, HValue *implicit_return_value)
Definition: hydrogen.cc:8070
bool TryInlineGetter(Handle< JSFunction > getter, Handle< Map > receiver_map, BailoutId ast_id, BailoutId return_id)
Definition: hydrogen.cc:8055
HInstruction * BuildStoreNamedField(PropertyAccessInfo *info, HValue *checked_object, HValue *value)
Definition: hydrogen.cc:5846
HInstruction * BuildLoadNamedField(PropertyAccessInfo *info, HValue *checked_object)
Definition: hydrogen.cc:5804
static bool NeedsWrappingFor(Type *type, Handle< JSFunction > target)
Definition: hydrogen.cc:6165
@ WRAP_AND_CALL
Definition: globals.h:473

References v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::accessor(), BuildCallConstantFunction(), v8::internal::HGraphBuilder::BuildCheckPrototypeMaps(), BuildLoadNamedField(), BuildStoreNamedField(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::constant(), DCHECK, v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::GetJSObjectFieldAccess(), v8::internal::HGraphBuilder::graph(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::has_holder(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::holder(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsAccessor(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsConstant(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsField(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsFound(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsLoad(), v8::internal::HGraphBuilder::isolate(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsTransition(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::map(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::name(), v8::internal::NeedsWrappingFor(), NULL, v8::internal::HGraphBuilder::Push(), PushArgumentsFromEnvironment(), TryInlineGetter(), TryInlineSetter(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::type(), and v8::internal::WRAP_AND_CALL.

Referenced by BuildNamedAccess(), and HandlePolymorphicNamedFieldAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildMonomorphicElementAccess()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildMonomorphicElementAccess ( HValue object,
HValue key,
HValue val,
HValue dependency,
Handle< Map map,
PropertyAccessType  access_type,
KeyedAccessStoreMode  store_mode 
)
private

Definition at line 6885 of file hydrogen.cc.

6892  {
6893  HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
6894  if (dependency) {
6895  checked_object->ClearDependsOnFlag(kElementsKind);
6896  }
6897 
6898  if (access_type == STORE && map->prototype()->IsJSObject()) {
6899  // monomorphic stores need a prototype chain check because shape
6900  // changes could allow callbacks on elements in the chain that
6901  // aren't compatible with monomorphic keyed stores.
6902  PrototypeIterator iter(map);
6903  JSObject* holder = NULL;
6904  while (!iter.IsAtEnd()) {
6905  holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
6906  iter.Advance();
6907  }
6908  DCHECK(holder && holder->IsJSObject());
6909 
6910  BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
6911  Handle<JSObject>(holder));
6912  }
6913 
6916  checked_object, key, val,
6917  map->instance_type() == JS_ARRAY_TYPE,
6918  map->elements_kind(), access_type,
6919  load_mode, store_mode);
6920 }
HInstruction * BuildUncheckedMonomorphicElementAccess(HValue *checked_object, HValue *key, HValue *val, bool is_js_array, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode, KeyedAccessStoreMode store_mode)
Definition: hydrogen.cc:2398
LoadKeyedHoleMode BuildKeyedHoleMode(Handle< Map > map)
Definition: hydrogen.cc:6869
Object * GetCurrent() const
Definition: prototype.h:62

References v8::internal::PrototypeIterator::Advance(), v8::internal::HGraphBuilder::BuildCheckPrototypeMaps(), BuildKeyedHoleMode(), v8::internal::HGraphBuilder::BuildUncheckedMonomorphicElementAccess(), DCHECK, v8::internal::PrototypeIterator::GetCurrent(), v8::internal::handle(), v8::internal::PrototypeIterator::IsAtEnd(), v8::internal::JS_ARRAY_TYPE, map, NULL, and v8::internal::STORE.

Referenced by HandleKeyedElementAccess(), and HandlePolymorphicElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildNamedAccess()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildNamedAccess ( PropertyAccessType  access,
BailoutId  ast_id,
BailoutId  reutrn_id,
Expression expr,
HValue object,
Handle< String name,
HValue value,
bool  is_uninitialized = false 
)
private

Definition at line 7288 of file hydrogen.cc.

7296  {
7297  SmallMapList* types;
7298  ComputeReceiverTypes(expr, object, &types, zone());
7299  DCHECK(types != NULL);
7300 
7301  if (types->length() > 0) {
7302  PropertyAccessInfo info(this, access, ToType(types->first()), name);
7303  if (!info.CanAccessAsMonomorphic(types)) {
7305  access, expr, ast_id, return_id, object, value, types, name);
7306  return NULL;
7307  }
7308 
7309  HValue* checked_object;
7310  // Type::Number() is only supported by polymorphic load/call handling.
7311  DCHECK(!info.type()->Is(Type::Number()));
7312  BuildCheckHeapObject(object);
7313  if (AreStringTypes(types)) {
7314  checked_object =
7315  Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7316  } else {
7317  checked_object = Add<HCheckMaps>(object, types);
7318  }
7319  return BuildMonomorphicAccess(
7320  &info, object, checked_object, value, ast_id, return_id);
7321  }
7322 
7323  return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized);
7324 }
HInstruction * BuildMonomorphicAccess(PropertyAccessInfo *info, HValue *object, HValue *checked_object, HValue *value, BailoutId ast_id, BailoutId return_id, bool can_inline_accessor=true)
Definition: hydrogen.cc:6172
HInstruction * BuildNamedGeneric(PropertyAccessType access, Expression *expr, HValue *object, Handle< String > name, HValue *value, bool is_uninitialized=false)
Definition: hydrogen.cc:6819
Type * ToType(Handle< Map > map)
Definition: hydrogen.cc:4513
void HandlePolymorphicNamedFieldAccess(PropertyAccessType access_type, Expression *expr, BailoutId ast_id, BailoutId return_id, HValue *object, HValue *value, SmallMapList *types, Handle< String > name)
Definition: hydrogen.cc:6250
static bool AreStringTypes(SmallMapList *types)
Definition: hydrogen.cc:6414
static bool ComputeReceiverTypes(Expression *expr, HValue *receiver, SmallMapList **t, Zone *zone)
Definition: hydrogen.cc:6397

References v8::internal::AreStringTypes(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), BuildMonomorphicAccess(), BuildNamedGeneric(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(), v8::internal::ComputeReceiverTypes(), DCHECK, HandlePolymorphicNamedFieldAccess(), v8::internal::TypeImpl< Config >::Is(), name, NULL, ToType(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::type(), and v8::internal::HGraphBuilder::zone().

Referenced by BuildLoad(), BuildStore(), and HandleKeyedElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildNamedGeneric()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildNamedGeneric ( PropertyAccessType  access,
Expression expr,
HValue object,
Handle< String name,
HValue value,
bool  is_uninitialized = false 
)
private

Definition at line 6819 of file hydrogen.cc.

6825  {
6826  if (is_uninitialized) {
6827  Add<HDeoptimize>("Insufficient type feedback for generic named access",
6829  }
6830  if (access_type == LOAD) {
6831  HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name);
6832  if (FLAG_vector_ics) {
6833  Handle<SharedFunctionInfo> current_shared =
6834  function_state()->compilation_info()->shared_info();
6835  result->SetVectorAndSlot(
6836  handle(current_shared->feedback_vector(), isolate()),
6837  expr->AsProperty()->PropertyFeedbackSlot());
6838  }
6839  return result;
6840  } else {
6841  return New<HStoreNamedGeneric>(object, name, value, function_strict_mode());
6842  }
6843 }

References function_state(), function_strict_mode(), v8::internal::handle(), v8::internal::HGraphBuilder::isolate(), v8::internal::LOAD, name, and v8::internal::Deoptimizer::SOFT.

Referenced by BuildNamedAccess(), HandlePolymorphicCallNamed(), and HandlePolymorphicNamedFieldAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildStore()

void v8::internal::HOptimizedGraphBuilder::BuildStore ( Expression expression,
Property *  prop,
BailoutId  ast_id,
BailoutId  return_id,
bool  is_uninitialized = false 
)
private

Definition at line 6422 of file hydrogen.cc.

6426  {
6427  if (!prop->key()->IsPropertyName()) {
6428  // Keyed store.
6429  HValue* value = environment()->ExpressionStackAt(0);
6430  HValue* key = environment()->ExpressionStackAt(1);
6431  HValue* object = environment()->ExpressionStackAt(2);
6432  bool has_side_effects = false;
6433  HandleKeyedElementAccess(object, key, value, expr, ast_id, return_id, STORE,
6434  &has_side_effects);
6435  Drop(3);
6436  Push(value);
6437  Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
6438  return ast_context()->ReturnValue(Pop());
6439  }
6440 
6441  // Named store.
6442  HValue* value = Pop();
6443  HValue* object = Pop();
6444 
6445  Literal* key = prop->key()->AsLiteral();
6446  Handle<String> name = Handle<String>::cast(key->value());
6447  DCHECK(!name.is_null());
6448 
6449  HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr,
6450  object, name, value, is_uninitialized);
6451  if (instr == NULL) return;
6452 
6453  if (!ast_context()->IsEffect()) Push(value);
6454  AddInstruction(instr);
6455  if (instr->HasObservableSideEffects()) {
6456  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6457  }
6458  if (!ast_context()->IsEffect()) Drop(1);
6459  return ast_context()->ReturnValue(value);
6460 }

References v8::internal::HGraphBuilder::AddInstruction(), ast_context(), BuildNamedAccess(), v8::internal::Handle< T >::cast(), DCHECK, Drop(), v8::internal::HGraphBuilder::environment(), HandleKeyedElementAccess(), v8::internal::HValue::HasObservableSideEffects(), name, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnValue(), and v8::internal::STORE.

Referenced by BuildStoreForEffect(), HandleCompoundAssignment(), and HandlePropertyAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildStoreForEffect()

void v8::internal::HOptimizedGraphBuilder::BuildStoreForEffect ( Expression expression,
Property *  prop,
BailoutId  ast_id,
BailoutId  return_id,
HValue object,
HValue key,
HValue value 
)
private

Definition at line 9964 of file hydrogen.cc.

9970  {
9971  EffectContext for_effect(this);
9972  Push(object);
9973  if (key != NULL) Push(key);
9974  Push(value);
9975  BuildStore(expr, prop, ast_id, return_id);
9976 }
void BuildStore(Expression *expression, Property *prop, BailoutId ast_id, BailoutId return_id, bool is_uninitialized=false)
Definition: hydrogen.cc:6422

References BuildStore(), NULL, and v8::internal::HGraphBuilder::Push().

+ Here is the call graph for this function:

◆ BuildStoreNamedField()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildStoreNamedField ( PropertyAccessInfo info,
HValue checked_object,
HValue value 
)
private

Definition at line 5846 of file hydrogen.cc.

5849  {
5850  bool transition_to_field = info->IsTransition();
5851  // TODO(verwaest): Move this logic into PropertyAccessInfo.
5852  HObjectAccess field_access = info->access();
5853 
5854  HStoreNamedField *instr;
5855  if (field_access.representation().IsDouble()) {
5856  HObjectAccess heap_number_access =
5857  field_access.WithRepresentation(Representation::Tagged());
5858  if (transition_to_field) {
5859  // The store requires a mutable HeapNumber to be allocated.
5860  NoObservableSideEffectsScope no_side_effects(this);
5861  HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5862 
5863  // TODO(hpayer): Allocation site pretenuring support.
5864  HInstruction* heap_number = Add<HAllocate>(heap_number_size,
5865  HType::HeapObject(),
5866  NOT_TENURED,
5869  heap_number, isolate()->factory()->mutable_heap_number_map());
5870  Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
5871  value);
5872  instr = New<HStoreNamedField>(checked_object->ActualValue(),
5873  heap_number_access,
5874  heap_number);
5875  } else {
5876  // Already holds a HeapNumber; load the box and write its value field.
5877  HInstruction* heap_number = Add<HLoadNamedField>(
5878  checked_object, static_cast<HValue*>(NULL), heap_number_access);
5879  instr = New<HStoreNamedField>(heap_number,
5880  HObjectAccess::ForHeapNumberValue(),
5882  }
5883  } else {
5884  if (field_access.representation().IsHeapObject()) {
5885  BuildCheckHeapObject(value);
5886  }
5887 
5888  if (!info->field_maps()->is_empty()) {
5889  DCHECK(field_access.representation().IsHeapObject());
5890  value = Add<HCheckMaps>(value, info->field_maps());
5891  }
5892 
5893  // This is a normal store.
5894  instr = New<HStoreNamedField>(
5895  checked_object->ActualValue(), field_access, value,
5896  transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5897  }
5898 
5899  if (transition_to_field) {
5900  Handle<Map> transition(info->transition());
5901  DCHECK(!transition->is_deprecated());
5902  instr->SetTransition(Add<HConstant>(transition));
5903  }
5904  return instr;
5905 }

References v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::access(), v8::internal::HValue::ActualValue(), v8::internal::HGraphBuilder::AddStoreMapConstant(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), DCHECK, v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::field_maps(), v8::internal::INITIALIZING_STORE, v8::internal::HGraphBuilder::isolate(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsTransition(), v8::internal::HeapNumber::kSize, v8::internal::MUTABLE_HEAP_NUMBER_TYPE, v8::internal::NOT_TENURED, NULL, v8::internal::STORE_TO_INITIALIZED_ENTRY, v8::internal::Representation::Tagged(), and v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::transition().

Referenced by BuildMonomorphicAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildStringCharCodeAt()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildStringCharCodeAt ( HValue string,
HValue index 
)
private

Definition at line 10091 of file hydrogen.cc.

10093  {
10094  if (string->IsConstant() && index->IsConstant()) {
10095  HConstant* c_string = HConstant::cast(string);
10096  HConstant* c_index = HConstant::cast(index);
10097  if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10098  int32_t i = c_index->NumberValueAsInteger32();
10099  Handle<String> s = c_string->StringValue();
10100  if (i < 0 || i >= s->length()) {
10101  return New<HConstant>(base::OS::nan_value());
10102  }
10103  return New<HConstant>(s->Get(i));
10104  }
10105  }
10106  string = BuildCheckString(string);
10107  index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
10108  return New<HStringCharCodeAt>(string, index);
10109 }
static double nan_value()
HValue * BuildCheckString(HValue *string)
Definition: hydrogen.cc:1278
HInstruction * AddLoadStringLength(HValue *string)
Definition: hydrogen.cc:6807

References v8::internal::HGraphBuilder::AddLoadStringLength(), v8::internal::HGraphBuilder::BuildCheckString(), and v8::base::OS::nan_value().

Referenced by BuildLoad(), and TryInlineBuiltinMethodCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildThisFunction()

HInstruction * v8::internal::HOptimizedGraphBuilder::BuildThisFunction ( )
private

Definition at line 10921 of file hydrogen.cc.

10921  {
10922  // If we share optimized code between different closures, the
10923  // this-function is not a constant, except inside an inlined body.
10924  if (function_state()->outer() != NULL) {
10925  return New<HConstant>(
10926  function_state()->compilation_info()->closure());
10927  } else {
10928  return New<HThisFunction>();
10929  }
10930 }

References function_state(), and NULL.

+ Here is the call graph for this function:

◆ call_context()

AstContext* v8::internal::HOptimizedGraphBuilder::call_context ( ) const
inlineprotected

Definition at line 2170 of file hydrogen.h.

2170  {
2171  return function_state()->call_context();
2172  }

References function_state().

Referenced by TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ClearInlinedTestContext()

void v8::internal::HOptimizedGraphBuilder::ClearInlinedTestContext ( )
inlineprotected

Definition at line 2179 of file hydrogen.h.

2179  {
2180  function_state()->ClearInlinedTestContext();
2181  }

References function_state().

Referenced by TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ context()

HValue* v8::internal::HOptimizedGraphBuilder::context ( )
inlinevirtual

Implements v8::internal::HGraphBuilder.

Definition at line 2113 of file hydrogen.h.

2113 { return environment()->context(); }

References v8::internal::HGraphBuilder::environment().

Referenced by BuildAllocateFixedTypedArray(), BuildArrayIndexOf(), BuildCallConstantFunction(), BuildContextChainWalk(), HandleCompoundAssignment(), HandleGlobalVariableAssignment(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::map(), NewArgumentAdaptorCall(), set_ast_context(), SetUpScope(), TryInline(), TryInlineApiCall(), TryInlineBuiltinFunctionCall(), TryInlineBuiltinMethodCall(), VisitLogicalExpression(), and VisitNot().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CreateJoin()

HBasicBlock * v8::internal::HOptimizedGraphBuilder::CreateJoin ( HBasicBlock *  first,
HBasicBlock *  second,
BailoutId  join_id 
)

Definition at line 3341 of file hydrogen.cc.

3343  {
3344  if (first == NULL) {
3345  return second;
3346  } else if (second == NULL) {
3347  return first;
3348  } else {
3349  HBasicBlock* join_block = graph()->CreateBasicBlock();
3350  Goto(first, join_block);
3351  Goto(second, join_block);
3352  join_block->SetJoinId(join_id);
3353  return join_block;
3354  }
3355 }

References v8::internal::HGraphBuilder::Goto(), v8::internal::HGraphBuilder::graph(), and NULL.

Referenced by VisitLogicalExpression(), and VisitNot().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CreateLoop()

HBasicBlock * v8::internal::HOptimizedGraphBuilder::CreateLoop ( IterationStatement statement,
HBasicBlock *  loop_entry,
HBasicBlock *  body_exit,
HBasicBlock *  loop_successor,
HBasicBlock *  break_block 
)
protected

Definition at line 3370 of file hydrogen.cc.

3374  {
3375  if (body_exit != NULL) Goto(body_exit, loop_entry);
3376  loop_entry->PostProcessLoopHeader(statement);
3377  if (break_block != NULL) {
3378  if (loop_successor != NULL) Goto(loop_successor, break_block);
3379  break_block->SetJoinId(statement->ExitId());
3380  return break_block;
3381  }
3382  return loop_successor;
3383 }

References v8::internal::BreakableStatement::ExitId(), v8::internal::HGraphBuilder::Goto(), and NULL.

+ Here is the call graph for this function:

◆ current_info()

CompilationInfo* v8::internal::HOptimizedGraphBuilder::current_info ( ) const
inlineprotected

Definition at line 2167 of file hydrogen.h.

2167  {
2168  return function_state()->compilation_info();
2169  }

References function_state().

Referenced by Bailout(), BuildCallConstantFunction(), BuildGraph(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::current_info(), HandleCompoundAssignment(), HandleGlobalVariableAssignment(), HandlePolymorphicCallNamed(), v8::internal::HOsrBuilder::HasOsrEntryAt(), InliningAstSize(), IsCallArrayInlineable(), LookupGlobalProperty(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::map(), TryCallApply(), TryInline(), and VisitDeclarations().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DEFINE_AST_VISITOR_SUBCLASS_MEMBERS()

v8::internal::HOptimizedGraphBuilder::DEFINE_AST_VISITOR_SUBCLASS_MEMBERS ( )

◆ DISALLOW_COPY_AND_ASSIGN()

v8::internal::HOptimizedGraphBuilder::DISALLOW_COPY_AND_ASSIGN ( HOptimizedGraphBuilder  )
private

◆ Drop()

void v8::internal::HOptimizedGraphBuilder::Drop ( int  n)
inlineprotected

Definition at line 2231 of file hydrogen.h.

2231 { environment()->Drop(n); }

References v8::internal::HGraphBuilder::environment().

Referenced by BuildArrayCall(), BuildArrayIndexOf(), BuildBinaryOperation(), BuildCompareInstruction(), BuildInlinedCallArray(), BuildLoad(), BuildStore(), HandlePolymorphicCallNamed(), TryArgumentsAccess(), TryCallApply(), TryInlineApiCall(), TryInlineBuiltinFunctionCall(), TryInlineBuiltinMethodCall(), and VisitLogicalExpression().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ EnsureArgumentsArePushedForAccess()

void v8::internal::HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess ( )
private

Definition at line 7209 of file hydrogen.cc.

7209  {
7210  // Outermost function already has arguments on the stack.
7211  if (function_state()->outer() == NULL) return;
7212 
7213  if (function_state()->arguments_pushed()) return;
7214 
7215  // Push arguments when entering inlined function.
7216  HEnterInlined* entry = function_state()->entry();
7217  entry->set_arguments_pushed();
7218 
7219  HArgumentsObject* arguments = entry->arguments_object();
7220  const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
7221 
7222  HInstruction* insert_after = entry;
7223  for (int i = 0; i < arguments_values->length(); i++) {
7224  HValue* argument = arguments_values->at(i);
7225  HInstruction* push_argument = New<HPushArguments>(argument);
7226  push_argument->InsertAfter(insert_after);
7227  insert_after = push_argument;
7228  }
7229 
7230  HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
7231  arguments_elements->ClearFlag(HValue::kUseGVN);
7232  arguments_elements->InsertAfter(insert_after);
7233  function_state()->set_arguments_elements(arguments_elements);
7234 }

References v8::internal::List< T, AllocationPolicy >::at(), function_state(), v8::internal::HInstruction::InsertAfter(), v8::internal::HValue::kUseGVN, and NULL.

Referenced by TryArgumentsAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ function_return()

HBasicBlock* v8::internal::HOptimizedGraphBuilder::function_return ( ) const
inlineprotected

Definition at line 2173 of file hydrogen.h.

2173  {
2174  return function_state()->function_return();
2175  }

References function_state().

Referenced by TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ function_state()

FunctionState* v8::internal::HOptimizedGraphBuilder::function_state ( ) const
inline

Definition at line 2123 of file hydrogen.h.

2123 { return function_state_; }

References function_state_.

Referenced by BuildKeyedGeneric(), BuildNamedGeneric(), BuildThisFunction(), call_context(), ClearInlinedTestContext(), current_info(), EnsureArgumentsArePushedForAccess(), function_return(), function_strict_mode(), inlined_test_context(), TryArgumentsAccess(), TryCallApply(), and TryInline().

+ Here is the caller graph for this function:

◆ function_strict_mode()

StrictMode v8::internal::HOptimizedGraphBuilder::function_strict_mode ( )
inlineprotected

Definition at line 2182 of file hydrogen.h.

2182  {
2183  return function_state()->compilation_info()->strict_mode();
2184  }

References function_state().

Referenced by BuildKeyedGeneric(), BuildNamedGeneric(), HandleGlobalVariableAssignment(), and VisitDelete().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandleCompoundAssignment()

void v8::internal::HOptimizedGraphBuilder::HandleCompoundAssignment ( Assignment *  expr)
private

Definition at line 6530 of file hydrogen.cc.

6530  {
6531  Expression* target = expr->target();
6532  VariableProxy* proxy = target->AsVariableProxy();
6533  Property* prop = target->AsProperty();
6534  DCHECK(proxy == NULL || prop == NULL);
6535 
6536  // We have a second position recorded in the FullCodeGenerator to have
6537  // type feedback for the binary operation.
6538  BinaryOperation* operation = expr->binary_operation();
6539 
6540  if (proxy != NULL) {
6541  Variable* var = proxy->var();
6542  if (var->mode() == LET) {
6543  return Bailout(kUnsupportedLetCompoundAssignment);
6544  }
6545 
6546  CHECK_ALIVE(VisitForValue(operation));
6547 
6548  switch (var->location()) {
6549  case Variable::UNALLOCATED:
6551  Top(),
6552  expr->AssignmentId());
6553  break;
6554 
6555  case Variable::PARAMETER:
6556  case Variable::LOCAL:
6557  if (var->mode() == CONST_LEGACY) {
6558  return Bailout(kUnsupportedConstCompoundAssignment);
6559  }
6560  BindIfLive(var, Top());
6561  break;
6562 
6563  case Variable::CONTEXT: {
6564  // Bail out if we try to mutate a parameter value in a function
6565  // using the arguments object. We do not (yet) correctly handle the
6566  // arguments property of the function.
6567  if (current_info()->scope()->arguments() != NULL) {
6568  // Parameters will be allocated to context slots. We have no
6569  // direct way to detect that the variable is a parameter so we do
6570  // a linear search of the parameter variables.
6571  int count = current_info()->scope()->num_parameters();
6572  for (int i = 0; i < count; ++i) {
6573  if (var == current_info()->scope()->parameter(i)) {
6574  Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
6575  }
6576  }
6577  }
6578 
6579  HStoreContextSlot::Mode mode;
6580 
6581  switch (var->mode()) {
6582  case LET:
6583  mode = HStoreContextSlot::kCheckDeoptimize;
6584  break;
6585  case CONST:
6586  // This case is checked statically so no need to
6587  // perform checks here
6588  UNREACHABLE();
6589  case CONST_LEGACY:
6590  return ast_context()->ReturnValue(Pop());
6591  default:
6592  mode = HStoreContextSlot::kNoCheck;
6593  }
6594 
6595  HValue* context = BuildContextChainWalk(var);
6596  HStoreContextSlot* instr = Add<HStoreContextSlot>(
6597  context, var->index(), mode, Top());
6598  if (instr->HasObservableSideEffects()) {
6599  Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6600  }
6601  break;
6602  }
6603 
6604  case Variable::LOOKUP:
6605  return Bailout(kCompoundAssignmentToLookupSlot);
6606  }
6607  return ast_context()->ReturnValue(Pop());
6608 
6609  } else if (prop != NULL) {
6610  CHECK_ALIVE(VisitForValue(prop->obj()));
6611  HValue* object = Top();
6612  HValue* key = NULL;
6613  if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
6614  CHECK_ALIVE(VisitForValue(prop->key()));
6615  key = Top();
6616  }
6617 
6618  CHECK_ALIVE(PushLoad(prop, object, key));
6619 
6620  CHECK_ALIVE(VisitForValue(expr->value()));
6621  HValue* right = Pop();
6622  HValue* left = Pop();
6623 
6624  Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
6625 
6626  BuildStore(expr, prop, expr->id(),
6627  expr->AssignmentId(), expr->IsUninitialized());
6628  } else {
6629  return Bailout(kInvalidLhsInCompoundAssignment);
6630  }
6631 }
HValue * BuildBinaryOperation(BinaryOperation *expr, HValue *left, HValue *right, PushBeforeSimulateBehavior push_sim_result)
Definition: hydrogen.cc:10224
void HandleGlobalVariableAssignment(Variable *var, HValue *value, BailoutId ast_id)
Definition: hydrogen.cc:6479
void BindIfLive(Variable *var, HValue *value)
Definition: hydrogen.h:2245
HValue * BuildContextChainWalk(Variable *var)
Definition: hydrogen.cc:5325
void VisitForValue(Expression *expr, ArgumentsAllowedFlag flag=ARGUMENTS_NOT_ALLOWED)
Definition: hydrogen.cc:4224
void PushLoad(Property *property, HValue *object, HValue *key)
Definition: hydrogen.cc:7327
int num_parameters() const
Definition: scopes.h:321
#define CHECK_ALIVE(call)
Definition: hydrogen.cc:4198
@ CONST_LEGACY
Definition: globals.h:671

References ast_context(), Bailout(), BindIfLive(), BuildBinaryOperation(), BuildContextChainWalk(), BuildStore(), CHECK_ALIVE, v8::internal::CONST, v8::internal::CONST_LEGACY, context(), v8::internal::Variable::CONTEXT, current_info(), DCHECK, HandleGlobalVariableAssignment(), v8::internal::Variable::index(), v8::internal::LET, v8::internal::Variable::LOCAL, v8::internal::Variable::location(), v8::internal::Variable::LOOKUP, v8::internal::Variable::mode(), mode(), NULL, v8::internal::Scope::num_parameters(), v8::internal::Variable::PARAMETER, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), PUSH_BEFORE_SIMULATE, PushLoad(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnValue(), v8::internal::CompilationInfo::scope(), v8::internal::HGraphBuilder::scope(), Top(), v8::internal::Variable::UNALLOCATED, UNREACHABLE, and VisitForValue().

+ Here is the call graph for this function:

◆ HandleGlobalVariableAssignment()

void v8::internal::HOptimizedGraphBuilder::HandleGlobalVariableAssignment ( Variable var,
HValue value,
BailoutId  ast_id 
)
private

Definition at line 6479 of file hydrogen.cc.

6482  {
6483  Handle<GlobalObject> global(current_info()->global_object());
6484  LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR);
6486  if (type == kUseCell) {
6487  Handle<PropertyCell> cell = it.GetPropertyCell();
6488  if (cell->type()->IsConstant()) {
6489  Handle<Object> constant = cell->type()->AsConstant()->Value();
6490  if (value->IsConstant()) {
6491  HConstant* c_value = HConstant::cast(value);
6492  if (!constant.is_identical_to(c_value->handle(isolate()))) {
6493  Add<HDeoptimize>("Constant global variable assignment",
6495  }
6496  } else {
6497  HValue* c_constant = Add<HConstant>(constant);
6498  IfBuilder builder(this);
6499  if (constant->IsNumber()) {
6500  builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
6501  } else {
6502  builder.If<HCompareObjectEqAndBranch>(value, c_constant);
6503  }
6504  builder.Then();
6505  builder.Else();
6506  Add<HDeoptimize>("Constant global variable assignment",
6508  builder.End();
6509  }
6510  }
6511  HInstruction* instr =
6512  Add<HStoreGlobalCell>(value, cell, it.property_details());
6513  if (instr->HasObservableSideEffects()) {
6514  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6515  }
6516  } else {
6517  HValue* global_object = Add<HLoadNamedField>(
6518  context(), static_cast<HValue*>(NULL),
6519  HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6520  HStoreNamedGeneric* instr =
6521  Add<HStoreNamedGeneric>(global_object, var->name(),
6522  value, function_strict_mode());
6523  USE(instr);
6524  DCHECK(instr->HasObservableSideEffects());
6525  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6526  }
6527 }
GlobalPropertyAccess LookupGlobalProperty(Variable *var, LookupIterator *it, PropertyAccessType access_type)
Definition: hydrogen.cc:5301

References context(), current_info(), DCHECK, v8::internal::Deoptimizer::EAGER, v8::internal::EQ, function_strict_mode(), v8::internal::Context::GLOBAL_OBJECT_INDEX, v8::internal::HValue::HasObservableSideEffects(), v8::internal::HGraphBuilder::isolate(), kUseCell, LookupGlobalProperty(), v8::internal::Variable::name(), NULL, v8::internal::REMOVABLE_SIMULATE, v8::internal::STORE, and USE().

Referenced by HandleCompoundAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandleKeyedElementAccess()

HValue * v8::internal::HOptimizedGraphBuilder::HandleKeyedElementAccess ( HValue obj,
HValue key,
HValue val,
Expression expr,
BailoutId  ast_id,
BailoutId  return_id,
PropertyAccessType  access_type,
bool has_side_effects 
)
private

Definition at line 7125 of file hydrogen.cc.

7128  {
7129  if (key->ActualValue()->IsConstant()) {
7130  Handle<Object> constant =
7131  HConstant::cast(key->ActualValue())->handle(isolate());
7132  uint32_t array_index;
7133  if (constant->IsString() &&
7134  !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
7135  if (!constant->IsUniqueName()) {
7136  constant = isolate()->factory()->InternalizeString(
7137  Handle<String>::cast(constant));
7138  }
7139  HInstruction* instr =
7140  BuildNamedAccess(access_type, ast_id, return_id, expr, obj,
7141  Handle<String>::cast(constant), val, false);
7142  if (instr == NULL || instr->IsLinked()) {
7143  *has_side_effects = false;
7144  } else {
7145  AddInstruction(instr);
7146  *has_side_effects = instr->HasObservableSideEffects();
7147  }
7148  return instr;
7149  }
7150  }
7151 
7152  DCHECK(!expr->IsPropertyName());
7153  HInstruction* instr = NULL;
7154 
7155  SmallMapList* types;
7156  bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
7157 
7158  bool force_generic = false;
7159  if (access_type == STORE &&
7160  (monomorphic || (types != NULL && !types->is_empty()))) {
7161  // Stores can't be mono/polymorphic if their prototype chain has dictionary
7162  // elements. However a receiver map that has dictionary elements itself
7163  // should be left to normal mono/poly behavior (the other maps may benefit
7164  // from highly optimized stores).
7165  for (int i = 0; i < types->length(); i++) {
7166  Handle<Map> current_map = types->at(i);
7167  if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7168  force_generic = true;
7169  monomorphic = false;
7170  break;
7171  }
7172  }
7173  }
7174 
7175  if (monomorphic) {
7176  Handle<Map> map = types->first();
7177  if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
7178  instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
7179  val));
7180  } else {
7181  BuildCheckHeapObject(obj);
7183  obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7184  }
7185  } else if (!force_generic && (types != NULL && !types->is_empty())) {
7187  expr, obj, key, val, types, access_type,
7188  expr->GetStoreMode(), has_side_effects);
7189  } else {
7190  if (access_type == STORE) {
7191  if (expr->IsAssignment() &&
7192  expr->AsAssignment()->HasNoTypeInformation()) {
7193  Add<HDeoptimize>("Insufficient type feedback for keyed store",
7195  }
7196  } else {
7197  if (expr->AsProperty()->HasNoTypeInformation()) {
7198  Add<HDeoptimize>("Insufficient type feedback for keyed load",
7200  }
7201  }
7202  instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val));
7203  }
7204  *has_side_effects = instr->HasObservableSideEffects();
7205  return instr;
7206 }
HInstruction * BuildMonomorphicElementAccess(HValue *object, HValue *key, HValue *val, HValue *dependency, Handle< Map > map, PropertyAccessType access_type, KeyedAccessStoreMode store_mode)
Definition: hydrogen.cc:6885
HInstruction * BuildKeyedGeneric(PropertyAccessType access_type, Expression *expr, HValue *object, HValue *key, HValue *value)
Definition: hydrogen.cc:6847
HValue * HandlePolymorphicElementAccess(Expression *expr, HValue *object, HValue *key, HValue *val, SmallMapList *maps, PropertyAccessType access_type, KeyedAccessStoreMode store_mode, bool *has_side_effects)
Definition: hydrogen.cc:6989

References v8::internal::HValue::ActualValue(), v8::internal::HGraphBuilder::AddInstruction(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), BuildKeyedGeneric(), BuildMonomorphicElementAccess(), BuildNamedAccess(), v8::internal::ComputeReceiverTypes(), DCHECK, v8::internal::Isolate::factory(), v8::internal::Expression::GetStoreMode(), HandlePolymorphicElementAccess(), v8::internal::HValue::HasObservableSideEffects(), v8::internal::HInstruction::IsLinked(), v8::internal::HGraphBuilder::isolate(), v8::internal::Expression::IsPropertyName(), map, NULL, v8::internal::Deoptimizer::SOFT, v8::internal::STORE, and v8::internal::HGraphBuilder::zone().

Referenced by BuildLoad(), and BuildStore().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandleLiteralCompareNil()

void v8::internal::HOptimizedGraphBuilder::HandleLiteralCompareNil ( CompareOperation *  expr,
Expression sub_expr,
NilValue  nil 
)
private

Definition at line 10893 of file hydrogen.cc.

10895  {
10896  DCHECK(!HasStackOverflow());
10897  DCHECK(current_block() != NULL);
10898  DCHECK(current_block()->HasPredecessor());
10899  DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
10900  if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
10901  CHECK_ALIVE(VisitForValue(sub_expr));
10902  HValue* value = Pop();
10903  if (expr->op() == Token::EQ_STRICT) {
10904  HConstant* nil_constant = nil == kNullValue
10905  ? graph()->GetConstantNull()
10906  : graph()->GetConstantUndefined();
10907  HCompareObjectEqAndBranch* instr =
10908  New<HCompareObjectEqAndBranch>(value, nil_constant);
10909  return ast_context()->ReturnControl(instr, expr->id());
10910  } else {
10911  DCHECK_EQ(Token::EQ, expr->op());
10912  Type* type = expr->combined_type()->Is(Type::None())
10913  ? Type::Any(zone()) : expr->combined_type();
10914  HIfContinuation continuation;
10915  BuildCompareNil(value, type, &continuation);
10916  return ast_context()->ReturnContinuation(&continuation, expr->id());
10917  }
10918 }
virtual void ReturnControl(HControlInstruction *instr, BailoutId ast_id)=0
virtual void ReturnContinuation(HIfContinuation *continuation, BailoutId ast_id)=0
void BuildCompareNil(HValue *value, Type *type, HIfContinuation *continuation)
Definition: hydrogen.cc:3023
bool Is(TypeImpl *that)
Definition: types.h:390
@ kNullValue
Definition: v8.h:97
@ None
Definition: v8.h:2211

References ast_context(), v8::internal::HGraphBuilder::BuildCompareNil(), CHECK_ALIVE, v8::internal::HGraphBuilder::current_block(), DCHECK, DCHECK_EQ, v8::internal::EQ, v8::internal::HGraphBuilder::graph(), v8::internal::HValue::id(), v8::internal::TypeImpl< Config >::Is(), v8::internal::kNullValue, v8::None, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnContinuation(), v8::internal::AstContext::ReturnControl(), v8::internal::HGraphBuilder::SetSourcePosition(), VisitForValue(), and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ HandleLiteralCompareTypeof()

void v8::internal::HOptimizedGraphBuilder::HandleLiteralCompareTypeof ( CompareOperation *  expr,
Expression sub_expr,
Handle< String check 
)
private

Definition at line 10640 of file hydrogen.cc.

10642  {
10643  CHECK_ALIVE(VisitForTypeOf(sub_expr));
10644  SetSourcePosition(expr->position());
10645  HValue* value = Pop();
10646  HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
10647  return ast_context()->ReturnControl(instr, expr->id());
10648 }
void VisitForTypeOf(Expression *expr)
Definition: hydrogen.cc:4231

References ast_context(), CHECK_ALIVE, v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnControl(), v8::internal::HGraphBuilder::SetSourcePosition(), and VisitForTypeOf().

+ Here is the call graph for this function:

◆ HandlePolymorphicCallNamed()

void v8::internal::HOptimizedGraphBuilder::HandlePolymorphicCallNamed ( Call *  expr,
HValue receiver,
SmallMapList *  types,
Handle< String name 
)
private

Definition at line 7508 of file hydrogen.cc.

7512  {
7513  int argument_count = expr->arguments()->length() + 1; // Includes receiver.
7514  FunctionSorter order[kMaxCallPolymorphism];
7515 
7516  bool handle_smi = false;
7517  bool handled_string = false;
7518  int ordered_functions = 0;
7519 
7520  int i;
7521  for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism;
7522  ++i) {
7523  PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7524  if (info.CanAccessMonomorphic() && info.IsConstant() &&
7525  info.constant()->IsJSFunction()) {
7526  if (info.type()->Is(Type::String())) {
7527  if (handled_string) continue;
7528  handled_string = true;
7529  }
7530  Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7531  if (info.type()->Is(Type::Number())) {
7532  handle_smi = true;
7533  }
7534  expr->set_target(target);
7535  order[ordered_functions++] = FunctionSorter(
7536  i, target->shared()->profiler_ticks(), InliningAstSize(target));
7537  }
7538  }
7539 
7540  std::sort(order, order + ordered_functions);
7541 
7542  if (i < types->length()) {
7543  types->Clear();
7544  ordered_functions = -1;
7545  }
7546 
7547  HBasicBlock* number_block = NULL;
7548  HBasicBlock* join = NULL;
7549  handled_string = false;
7550  int count = 0;
7551 
7552  for (int fn = 0; fn < ordered_functions; ++fn) {
7553  int i = order[fn].index();
7554  PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7555  if (info.type()->Is(Type::String())) {
7556  if (handled_string) continue;
7557  handled_string = true;
7558  }
7559  // Reloads the target.
7560  info.CanAccessMonomorphic();
7561  Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7562 
7563  expr->set_target(target);
7564  if (count == 0) {
7565  // Only needed once.
7566  join = graph()->CreateBasicBlock();
7567  if (handle_smi) {
7568  HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
7569  HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
7570  number_block = graph()->CreateBasicBlock();
7571  FinishCurrentBlock(New<HIsSmiAndBranch>(
7572  receiver, empty_smi_block, not_smi_block));
7573  GotoNoSimulate(empty_smi_block, number_block);
7574  set_current_block(not_smi_block);
7575  } else {
7576  BuildCheckHeapObject(receiver);
7577  }
7578  }
7579  ++count;
7580  HBasicBlock* if_true = graph()->CreateBasicBlock();
7581  HBasicBlock* if_false = graph()->CreateBasicBlock();
7582  HUnaryControlInstruction* compare;
7583 
7584  Handle<Map> map = info.map();
7585  if (info.type()->Is(Type::Number())) {
7586  Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
7587  compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
7588  } else if (info.type()->Is(Type::String())) {
7589  compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
7590  } else {
7591  compare = New<HCompareMap>(receiver, map, if_true, if_false);
7592  }
7593  FinishCurrentBlock(compare);
7594 
7595  if (info.type()->Is(Type::Number())) {
7596  GotoNoSimulate(if_true, number_block);
7597  if_true = number_block;
7598  }
7599 
7600  set_current_block(if_true);
7601 
7602  AddCheckPrototypeMaps(info.holder(), map);
7603 
7604  HValue* function = Add<HConstant>(expr->target());
7605  environment()->SetExpressionStackAt(0, function);
7606  Push(receiver);
7607  CHECK_ALIVE(VisitExpressions(expr->arguments()));
7608  bool needs_wrapping = NeedsWrappingFor(info.type(), target);
7609  bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
7610  if (FLAG_trace_inlining && try_inline) {
7611  Handle<JSFunction> caller = current_info()->closure();
7612  SmartArrayPointer<char> caller_name =
7613  caller->shared()->DebugName()->ToCString();
7614  PrintF("Trying to inline the polymorphic call to %s from %s\n",
7615  name->ToCString().get(),
7616  caller_name.get());
7617  }
7618  if (try_inline && TryInlineCall(expr)) {
7619  // Trying to inline will signal that we should bailout from the
7620  // entire compilation by setting stack overflow on the visitor.
7621  if (HasStackOverflow()) return;
7622  } else {
7623  // Since HWrapReceiver currently cannot actually wrap numbers and strings,
7624  // use the regular CallFunctionStub for method calls to wrap the receiver.
7625  // TODO(verwaest): Support creation of value wrappers directly in
7626  // HWrapReceiver.
7627  HInstruction* call = needs_wrapping
7628  ? NewUncasted<HCallFunction>(
7629  function, argument_count, WRAP_AND_CALL)
7630  : BuildCallConstantFunction(target, argument_count);
7631  PushArgumentsFromEnvironment(argument_count);
7632  AddInstruction(call);
7633  Drop(1); // Drop the function.
7634  if (!ast_context()->IsEffect()) Push(call);
7635  }
7636 
7637  if (current_block() != NULL) Goto(join);
7638  set_current_block(if_false);
7639  }
7640 
7641  // Finish up. Unconditionally deoptimize if we've handled all the maps we
7642  // know about and do not want to handle ones we've never seen. Otherwise
7643  // use a generic IC.
7644  if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7645  FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
7646  } else {
7647  Property* prop = expr->expression()->AsProperty();
7648  HInstruction* function = BuildNamedGeneric(
7649  LOAD, prop, receiver, name, NULL, prop->IsUninitialized());
7650  AddInstruction(function);
7651  Push(function);
7652  AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7653 
7654  environment()->SetExpressionStackAt(1, function);
7655  environment()->SetExpressionStackAt(0, receiver);
7656  CHECK_ALIVE(VisitExpressions(expr->arguments()));
7657 
7658  CallFunctionFlags flags = receiver->type().IsJSObject()
7660  HInstruction* call = New<HCallFunction>(
7661  function, argument_count, flags);
7662 
7663  PushArgumentsFromEnvironment(argument_count);
7664 
7665  Drop(1); // Function.
7666 
7667  if (join != NULL) {
7668  AddInstruction(call);
7669  if (!ast_context()->IsEffect()) Push(call);
7670  Goto(join);
7671  } else {
7672  return ast_context()->ReturnInstruction(call, expr->id());
7673  }
7674  }
7675 
7676  // We assume that control flow is always live after an expression. So
7677  // even without predecessors to the join block, we set it as the exit
7678  // block and continue by adding instructions there.
7679  DCHECK(join != NULL);
7680  if (join->HasPredecessor()) {
7681  set_current_block(join);
7682  join->SetJoinId(expr->id());
7683  if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
7684  } else {
7686  }
7687 }
Handle< JSFunction > closure() const
Definition: compiler.h:111
void FinishExitWithHardDeoptimization(const char *reason)
Definition: hydrogen.cc:1272
void GotoNoSimulate(HBasicBlock *from, HBasicBlock *target)
Definition: hydrogen.h:1091
void FinishCurrentBlock(HControlInstruction *last)
Definition: hydrogen.cc:1198
static const int kMaxCallPolymorphism
Definition: hydrogen.h:2145
void VisitExpressions(ZoneList< Expression * > *exprs)
Definition: hydrogen.cc:4246
int InliningAstSize(Handle< JSFunction > target)
Definition: hydrogen.cc:7712
void AddCheckPrototypeMaps(Handle< JSObject > holder, Handle< Map > receiver_map)
Definition: hydrogen.cc:7421
void PrintF(const char *format,...)
Definition: utils.cc:80
@ NO_CALL_FUNCTION_FLAGS
Definition: globals.h:469
@ CALL_AS_METHOD
Definition: globals.h:470

References AddCheckPrototypeMaps(), v8::internal::HGraphBuilder::AddInstruction(), v8::internal::HGraphBuilder::AddSimulate(), ast_context(), BuildCallConstantFunction(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), BuildNamedGeneric(), v8::internal::CALL_AS_METHOD, v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic(), v8::internal::Handle< T >::cast(), CHECK_ALIVE, v8::internal::CompilationInfo::closure(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::constant(), v8::internal::HGraphBuilder::current_block(), current_info(), DCHECK, Drop(), v8::internal::HGraphBuilder::environment(), v8::internal::Isolate::factory(), v8::internal::HGraphBuilder::FinishCurrentBlock(), v8::internal::HGraphBuilder::FinishExitWithHardDeoptimization(), v8::internal::anonymous_namespace{flags.cc}::flags, v8::internal::SmartPointerBase< Deallocator, T >::get(), v8::internal::HGraphBuilder::Goto(), v8::internal::HGraphBuilder::GotoNoSimulate(), v8::internal::HGraphBuilder::graph(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::holder(), v8::internal::HValue::id(), v8::internal::FunctionSorter::index(), InliningAstSize(), v8::internal::TypeImpl< Config >::Is(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::IsConstant(), v8::internal::HGraphBuilder::isolate(), kMaxCallPolymorphism, v8::internal::LOAD, map, v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::map(), name, v8::internal::NeedsWrappingFor(), v8::internal::NO_CALL_FUNCTION_FLAGS, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::PrintF(), v8::internal::HGraphBuilder::Push(), PushArgumentsFromEnvironment(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnInstruction(), v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::set_current_block(), ToType(), TryInlineCall(), v8::internal::HValue::type(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::type(), VisitExpressions(), and v8::internal::WRAP_AND_CALL.

+ Here is the call graph for this function:

◆ HandlePolymorphicElementAccess()

HValue * v8::internal::HOptimizedGraphBuilder::HandlePolymorphicElementAccess ( Expression expr,
HValue object,
HValue key,
HValue val,
SmallMapList *  maps,
PropertyAccessType  access_type,
KeyedAccessStoreMode  store_mode,
bool has_side_effects 
)
private

Definition at line 6989 of file hydrogen.cc.

6997  {
6998  *has_side_effects = false;
6999  BuildCheckHeapObject(object);
7000 
7001  if (access_type == LOAD) {
7002  HInstruction* consolidated_load =
7003  TryBuildConsolidatedElementLoad(object, key, val, maps);
7004  if (consolidated_load != NULL) {
7005  *has_side_effects |= consolidated_load->HasObservableSideEffects();
7006  return consolidated_load;
7007  }
7008  }
7009 
7010  // Elements_kind transition support.
7011  MapHandleList transition_target(maps->length());
7012  // Collect possible transition targets.
7013  MapHandleList possible_transitioned_maps(maps->length());
7014  for (int i = 0; i < maps->length(); ++i) {
7015  Handle<Map> map = maps->at(i);
7016  ElementsKind elements_kind = map->elements_kind();
7017  if (IsFastElementsKind(elements_kind) &&
7018  elements_kind != GetInitialFastElementsKind()) {
7019  possible_transitioned_maps.Add(map);
7020  }
7021  if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
7022  HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key,
7023  val);
7024  *has_side_effects = result->HasObservableSideEffects();
7025  return AddInstruction(result);
7026  }
7027  }
7028  // Get transition target for each map (NULL == no transition).
7029  for (int i = 0; i < maps->length(); ++i) {
7030  Handle<Map> map = maps->at(i);
7031  Handle<Map> transitioned_map =
7032  map->FindTransitionedMap(&possible_transitioned_maps);
7033  transition_target.Add(transitioned_map);
7034  }
7035 
7036  MapHandleList untransitionable_maps(maps->length());
7037  HTransitionElementsKind* transition = NULL;
7038  for (int i = 0; i < maps->length(); ++i) {
7039  Handle<Map> map = maps->at(i);
7040  DCHECK(map->IsMap());
7041  if (!transition_target.at(i).is_null()) {
7043  map->elements_kind(),
7044  transition_target.at(i)->elements_kind()));
7045  transition = Add<HTransitionElementsKind>(object, map,
7046  transition_target.at(i));
7047  } else {
7048  untransitionable_maps.Add(map);
7049  }
7050  }
7051 
7052  // If only one map is left after transitioning, handle this case
7053  // monomorphically.
7054  DCHECK(untransitionable_maps.length() >= 1);
7055  if (untransitionable_maps.length() == 1) {
7056  Handle<Map> untransitionable_map = untransitionable_maps[0];
7057  HInstruction* instr = NULL;
7058  if (untransitionable_map->has_slow_elements_kind() ||
7059  !untransitionable_map->IsJSObjectMap()) {
7060  instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7061  val));
7062  } else {
7064  object, key, val, transition, untransitionable_map, access_type,
7065  store_mode);
7066  }
7067  *has_side_effects |= instr->HasObservableSideEffects();
7068  return access_type == STORE ? NULL : instr;
7069  }
7070 
7071  HBasicBlock* join = graph()->CreateBasicBlock();
7072 
7073  for (int i = 0; i < untransitionable_maps.length(); ++i) {
7074  Handle<Map> map = untransitionable_maps[i];
7075  if (!map->IsJSObjectMap()) continue;
7076  ElementsKind elements_kind = map->elements_kind();
7077  HBasicBlock* this_map = graph()->CreateBasicBlock();
7078  HBasicBlock* other_map = graph()->CreateBasicBlock();
7079  HCompareMap* mapcompare =
7080  New<HCompareMap>(object, map, this_map, other_map);
7081  FinishCurrentBlock(mapcompare);
7082 
7083  set_current_block(this_map);
7084  HInstruction* access = NULL;
7085  if (IsDictionaryElementsKind(elements_kind)) {
7086  access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7087  val));
7088  } else {
7089  DCHECK(IsFastElementsKind(elements_kind) ||
7090  IsExternalArrayElementsKind(elements_kind) ||
7091  IsFixedTypedArrayElementsKind(elements_kind));
7093  // Happily, mapcompare is a checked object.
7095  mapcompare, key, val,
7096  map->instance_type() == JS_ARRAY_TYPE,
7097  elements_kind, access_type,
7098  load_mode,
7099  store_mode);
7100  }
7101  *has_side_effects |= access->HasObservableSideEffects();
7102  // The caller will use has_side_effects and add a correct Simulate.
7103  access->SetFlag(HValue::kHasNoObservableSideEffects);
7104  if (access_type == LOAD) {
7105  Push(access);
7106  }
7107  NoObservableSideEffectsScope scope(this);
7108  GotoNoSimulate(join);
7109  set_current_block(other_map);
7110  }
7111 
7112  // Ensure that we visited at least one map above that goes to join. This is
7113  // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
7114  // rather than joining the join block. If this becomes an issue, insert a
7115  // generic access in the case length() == 0.
7116  DCHECK(join->predecessors()->length() > 0);
7117  // Deopt if none of the cases matched.
7118  NoObservableSideEffectsScope scope(this);
7119  FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
7120  set_current_block(join);
7121  return access_type == STORE ? NULL : Pop();
7122 }
HInstruction * TryBuildConsolidatedElementLoad(HValue *object, HValue *key, HValue *val, SmallMapList *maps)
Definition: hydrogen.cc:6923
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:12775
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:95
@ SLOPPY_ARGUMENTS_ELEMENTS
Definition: elements-kind.h:31
bool IsDictionaryElementsKind(ElementsKind kind)
Definition: elements-kind.h:85
List< Handle< Map > > MapHandleList
Definition: list.h:197
bool IsFixedTypedArrayElementsKind(ElementsKind kind)
ElementsKind GetInitialFastElementsKind()
Definition: elements-kind.h:78

References v8::internal::List< T, AllocationPolicy >::Add(), v8::internal::HGraphBuilder::AddInstruction(), v8::internal::List< T, AllocationPolicy >::at(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), BuildKeyedGeneric(), BuildKeyedHoleMode(), BuildMonomorphicElementAccess(), v8::internal::HGraphBuilder::BuildUncheckedMonomorphicElementAccess(), DCHECK, v8::internal::HGraphBuilder::FinishCurrentBlock(), v8::internal::HGraphBuilder::FinishExitWithHardDeoptimization(), v8::internal::GetInitialFastElementsKind(), v8::internal::HGraphBuilder::GotoNoSimulate(), v8::internal::HGraphBuilder::graph(), v8::internal::HValue::HasObservableSideEffects(), v8::internal::Handle< T >::is_null(), v8::internal::IsDictionaryElementsKind(), v8::internal::IsExternalArrayElementsKind(), v8::internal::IsFastElementsKind(), v8::internal::IsFixedTypedArrayElementsKind(), v8::internal::Map::IsValidElementsTransition(), v8::internal::JS_ARRAY_TYPE, v8::internal::HValue::kHasNoObservableSideEffects, v8::internal::LOAD, map, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::HGraphBuilder::scope(), v8::internal::HGraphBuilder::set_current_block(), v8::internal::HValue::SetFlag(), v8::internal::SLOPPY_ARGUMENTS_ELEMENTS, v8::internal::STORE, and TryBuildConsolidatedElementLoad().

Referenced by HandleKeyedElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandlePolymorphicNamedFieldAccess()

void v8::internal::HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess ( PropertyAccessType  access_type,
Expression expr,
BailoutId  ast_id,
BailoutId  return_id,
HValue object,
HValue value,
SmallMapList *  types,
Handle< String name 
)
private

Definition at line 6250 of file hydrogen.cc.

6258  {
6259  // Something did not match; must use a polymorphic load.
6260  int count = 0;
6261  HBasicBlock* join = NULL;
6262  HBasicBlock* number_block = NULL;
6263  bool handled_string = false;
6264 
6265  bool handle_smi = false;
6267  int i;
6268  for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
6269  PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
6270  if (info.type()->Is(Type::String())) {
6271  if (handled_string) continue;
6272  handled_string = true;
6273  }
6274  if (info.CanAccessMonomorphic()) {
6275  count++;
6276  if (info.type()->Is(Type::Number())) {
6277  handle_smi = true;
6278  break;
6279  }
6280  }
6281  }
6282 
6283  if (i < types->length()) {
6284  count = -1;
6285  types->Clear();
6286  } else {
6287  count = 0;
6288  }
6289  HControlInstruction* smi_check = NULL;
6290  handled_string = false;
6291 
6292  for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
6293  PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
6294  if (info.type()->Is(Type::String())) {
6295  if (handled_string) continue;
6296  handled_string = true;
6297  }
6298  if (!info.CanAccessMonomorphic()) continue;
6299 
6300  if (count == 0) {
6301  join = graph()->CreateBasicBlock();
6302  if (handle_smi) {
6303  HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6304  HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6305  number_block = graph()->CreateBasicBlock();
6306  smi_check = New<HIsSmiAndBranch>(
6307  object, empty_smi_block, not_smi_block);
6308  FinishCurrentBlock(smi_check);
6309  GotoNoSimulate(empty_smi_block, number_block);
6310  set_current_block(not_smi_block);
6311  } else {
6312  BuildCheckHeapObject(object);
6313  }
6314  }
6315  ++count;
6316  HBasicBlock* if_true = graph()->CreateBasicBlock();
6317  HBasicBlock* if_false = graph()->CreateBasicBlock();
6318  HUnaryControlInstruction* compare;
6319 
6320  HValue* dependency;
6321  if (info.type()->Is(Type::Number())) {
6322  Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6323  compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
6324  dependency = smi_check;
6325  } else if (info.type()->Is(Type::String())) {
6326  compare = New<HIsStringAndBranch>(object, if_true, if_false);
6327  dependency = compare;
6328  } else {
6329  compare = New<HCompareMap>(object, info.map(), if_true, if_false);
6330  dependency = compare;
6331  }
6332  FinishCurrentBlock(compare);
6333 
6334  if (info.type()->Is(Type::Number())) {
6335  GotoNoSimulate(if_true, number_block);
6336  if_true = number_block;
6337  }
6338 
6339  set_current_block(if_true);
6340 
6341  HInstruction* access = BuildMonomorphicAccess(
6342  &info, object, dependency, value, ast_id,
6343  return_id, FLAG_polymorphic_inlining);
6344 
6345  HValue* result = NULL;
6346  switch (access_type) {
6347  case LOAD:
6348  result = access;
6349  break;
6350  case STORE:
6351  result = value;
6352  break;
6353  }
6354 
6355  if (access == NULL) {
6356  if (HasStackOverflow()) return;
6357  } else {
6358  if (!access->IsLinked()) AddInstruction(access);
6359  if (!ast_context()->IsEffect()) Push(result);
6360  }
6361 
6362  if (current_block() != NULL) Goto(join);
6363  set_current_block(if_false);
6364  }
6365 
6366  // Finish up. Unconditionally deoptimize if we've handled all the maps we
6367  // know about and do not want to handle ones we've never seen. Otherwise
6368  // use a generic IC.
6369  if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
6370  FinishExitWithHardDeoptimization("Uknown map in polymorphic access");
6371  } else {
6372  HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name,
6373  value);
6374  AddInstruction(instr);
6375  if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6376 
6377  if (join != NULL) {
6378  Goto(join);
6379  } else {
6380  Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6381  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6382  return;
6383  }
6384  }
6385 
6386  DCHECK(join != NULL);
6387  if (join->HasPredecessor()) {
6388  join->SetJoinId(ast_id);
6389  set_current_block(join);
6390  if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6391  } else {
6393  }
6394 }
static const int kMaxStorePolymorphism
Definition: hydrogen.h:2147
static const int kMaxLoadPolymorphism
Definition: hydrogen.h:2146

References v8::internal::HGraphBuilder::AddInstruction(), ast_context(), v8::internal::HGraphBuilder::BuildCheckHeapObject(), BuildMonomorphicAccess(), BuildNamedGeneric(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic(), v8::internal::HGraphBuilder::current_block(), DCHECK, v8::internal::Isolate::factory(), v8::internal::HGraphBuilder::FinishCurrentBlock(), v8::internal::HGraphBuilder::FinishExitWithHardDeoptimization(), v8::internal::HGraphBuilder::Goto(), v8::internal::HGraphBuilder::GotoNoSimulate(), v8::internal::HGraphBuilder::graph(), v8::internal::TypeImpl< Config >::Is(), v8::internal::HInstruction::IsLinked(), v8::internal::HGraphBuilder::isolate(), kMaxLoadPolymorphism, kMaxStorePolymorphism, v8::internal::LOAD, v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::map(), name, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::set_current_block(), v8::internal::STATIC_ASSERT(), v8::internal::STORE, ToType(), and v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::type().

Referenced by BuildNamedAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ HandlePropertyAssignment()

void v8::internal::HOptimizedGraphBuilder::HandlePropertyAssignment ( Assignment *  expr)
private

Definition at line 6463 of file hydrogen.cc.

6463  {
6464  Property* prop = expr->target()->AsProperty();
6465  DCHECK(prop != NULL);
6466  CHECK_ALIVE(VisitForValue(prop->obj()));
6467  if (!prop->key()->IsPropertyName()) {
6468  CHECK_ALIVE(VisitForValue(prop->key()));
6469  }
6470  CHECK_ALIVE(VisitForValue(expr->value()));
6471  BuildStore(expr, prop, expr->id(),
6472  expr->AssignmentId(), expr->IsUninitialized());
6473 }

References BuildStore(), CHECK_ALIVE, DCHECK, NULL, and VisitForValue().

+ Here is the call graph for this function:

◆ ImplicitReceiverFor()

HValue * v8::internal::HOptimizedGraphBuilder::ImplicitReceiverFor ( HValue function,
Handle< JSFunction target 
)
private

Definition at line 8767 of file hydrogen.cc.

8768  {
8769  SharedFunctionInfo* shared = target->shared();
8770  if (shared->strict_mode() == SLOPPY && !shared->native()) {
8771  // Cannot embed a direct reference to the global proxy
8772  // as is it dropped on deserialization.
8773  CHECK(!isolate()->serializer_enabled());
8774  Handle<JSObject> global_proxy(target->context()->global_proxy());
8775  return Add<HConstant>(global_proxy);
8776  }
8777  return graph()->GetConstantUndefined();
8778 }
#define CHECK(condition)
Definition: logging.h:36

References CHECK, v8::internal::HGraphBuilder::graph(), v8::internal::HGraphBuilder::isolate(), v8::internal::SLOPPY, and v8::internal::SharedFunctionInfo::strict_mode().

+ Here is the call graph for this function:

◆ inlined_test_context()

TestContext* v8::internal::HOptimizedGraphBuilder::inlined_test_context ( ) const
inlineprotected

Definition at line 2176 of file hydrogen.h.

2176  {
2177  return function_state()->test_context();
2178  }

References function_state().

Referenced by TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ InliningAstSize()

int v8::internal::HOptimizedGraphBuilder::InliningAstSize ( Handle< JSFunction target)
private

Definition at line 7712 of file hydrogen.cc.

7712  {
7713  if (!FLAG_use_inlining) return kNotInlinable;
7714 
7715  // Precondition: call is monomorphic and we have found a target with the
7716  // appropriate arity.
7717  Handle<JSFunction> caller = current_info()->closure();
7718  Handle<SharedFunctionInfo> target_shared(target->shared());
7719 
7720  // Always inline builtins marked for inlining.
7721  if (target->IsBuiltin()) {
7722  return target_shared->inline_builtin() ? 0 : kNotInlinable;
7723  }
7724 
7725  if (target_shared->IsApiFunction()) {
7726  TraceInline(target, caller, "target is api function");
7727  return kNotInlinable;
7728  }
7729 
7730  // Do a quick check on source code length to avoid parsing large
7731  // inlining candidates.
7732  if (target_shared->SourceSize() >
7733  Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
7734  TraceInline(target, caller, "target text too big");
7735  return kNotInlinable;
7736  }
7737 
7738  // Target must be inlineable.
7739  if (!target_shared->IsInlineable()) {
7740  TraceInline(target, caller, "target not inlineable");
7741  return kNotInlinable;
7742  }
7743  if (target_shared->DisableOptimizationReason() != kNoReason) {
7744  TraceInline(target, caller, "target contains unsupported syntax [early]");
7745  return kNotInlinable;
7746  }
7747 
7748  int nodes_added = target_shared->ast_node_count();
7749  return nodes_added;
7750 }
void TraceInline(Handle< JSFunction > target, Handle< JSFunction > caller, const char *failure_reason)
Definition: hydrogen.cc:7690
static const int kUnlimitedMaxInlinedSourceSize
Definition: hydrogen.h:2151
static LifetimePosition Min(LifetimePosition a, LifetimePosition b)
static const int kNotInlinable
Definition: hydrogen.cc:7709

References v8::internal::CompilationInfo::closure(), current_info(), v8::internal::kNotInlinable, kUnlimitedMaxInlinedSourceSize, v8::internal::Min(), and TraceInline().

Referenced by HandlePolymorphicCallNamed(), and TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsCallArrayInlineable()

bool v8::internal::HOptimizedGraphBuilder::IsCallArrayInlineable ( int  argument_count,
Handle< AllocationSite site 
)
private

Definition at line 9217 of file hydrogen.cc.

9219  {
9220  Handle<JSFunction> caller = current_info()->closure();
9221  Handle<JSFunction> target = array_function();
9222  // We should have the function plus array arguments on the environment stack.
9223  DCHECK(environment()->length() >= (argument_count + 1));
9224  DCHECK(!site.is_null());
9225 
9226  bool inline_ok = false;
9227  if (site->CanInlineCall()) {
9228  // We also want to avoid inlining in certain 1 argument scenarios.
9229  if (argument_count == 1) {
9230  HValue* argument = Top();
9231  if (argument->IsConstant()) {
9232  // Do not inline if the constant length argument is not a smi or
9233  // outside the valid range for unrolled loop initialization.
9234  HConstant* constant_argument = HConstant::cast(argument);
9235  if (constant_argument->HasSmiValue()) {
9236  int value = constant_argument->Integer32Value();
9237  inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
9238  if (!inline_ok) {
9239  TraceInline(target, caller,
9240  "Constant length outside of valid inlining range.");
9241  }
9242  }
9243  } else {
9244  TraceInline(target, caller,
9245  "Dont inline [new] Array(n) where n isn't constant.");
9246  }
9247  } else if (argument_count == 0) {
9248  inline_ok = true;
9249  } else {
9250  TraceInline(target, caller, "Too many arguments to inline.");
9251  }
9252  } else {
9253  TraceInline(target, caller, "AllocationSite requested no inlining.");
9254  }
9255 
9256  if (inline_ok) {
9257  TraceInline(target, caller, NULL);
9258  }
9259  return inline_ok;
9260 }
static const int kElementLoopUnrollThreshold
Definition: hydrogen.h:1308

References array_function(), v8::internal::CompilationInfo::closure(), current_info(), DCHECK, v8::internal::HGraphBuilder::environment(), v8::internal::Handle< T >::is_null(), v8::internal::HGraphBuilder::kElementLoopUnrollThreshold, NULL, Top(), and TraceInline().

Referenced by BuildArrayCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsEligibleForEnvironmentLivenessAnalysis()

bool v8::internal::HOptimizedGraphBuilder::IsEligibleForEnvironmentLivenessAnalysis ( Variable var,
int  index,
HValue value,
HEnvironment *  env 
)
inlineprotected

Definition at line 2233 of file hydrogen.h.

2236  {
2237  if (!FLAG_analyze_environment_liveness) return false;
2238  // |this| and |arguments| are always live; zapping parameters isn't
2239  // safe because function.arguments can inspect them at any time.
2240  return !var->is_this() &&
2241  !var->is_arguments() &&
2242  !value->IsArgumentsObject() &&
2243  env->is_local_index(index);
2244  }

References v8::internal::Variable::is_arguments(), and v8::internal::Variable::is_this().

Referenced by BindIfLive(), and LookupAndMakeLive().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ JoinContinue()

HBasicBlock * v8::internal::HOptimizedGraphBuilder::JoinContinue ( IterationStatement statement,
HBasicBlock *  exit_block,
HBasicBlock *  continue_block 
)
protected

Definition at line 3358 of file hydrogen.cc.

3360  {
3361  if (continue_block != NULL) {
3362  if (exit_block != NULL) Goto(exit_block, continue_block);
3363  continue_block->SetJoinId(statement->ContinueId());
3364  return continue_block;
3365  }
3366  return exit_block;
3367 }

References v8::internal::IterationStatement::ContinueId(), v8::internal::HGraphBuilder::Goto(), and NULL.

+ Here is the call graph for this function:

◆ LookupAndMakeLive()

HValue* v8::internal::HOptimizedGraphBuilder::LookupAndMakeLive ( Variable var)
inlineprotected

Definition at line 2259 of file hydrogen.h.

2259  {
2260  HEnvironment* env = environment();
2261  int index = env->IndexFor(var);
2262  HValue* value = env->Lookup(index);
2263  if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2264  HEnvironmentMarker* lookup =
2265  Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2266  USE(lookup);
2267 #ifdef DEBUG
2268  lookup->set_closure(env->closure());
2269 #endif
2270  }
2271  return value;
2272  }

References v8::internal::HGraphBuilder::environment(), IsEligibleForEnvironmentLivenessAnalysis(), and USE().

Referenced by TryCallApply().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ LookupGlobalProperty()

HOptimizedGraphBuilder::GlobalPropertyAccess v8::internal::HOptimizedGraphBuilder::LookupGlobalProperty ( Variable var,
LookupIterator *  it,
PropertyAccessType  access_type 
)
private

Definition at line 5301 of file hydrogen.cc.

5302  {
5303  if (var->is_this() || !current_info()->has_global_object()) {
5304  return kUseGeneric;
5305  }
5306 
5307  switch (it->state()) {
5309  case LookupIterator::ACCESS_CHECK:
5310  case LookupIterator::INTERCEPTOR:
5311  case LookupIterator::NOT_FOUND:
5312  return kUseGeneric;
5313  case LookupIterator::DATA:
5314  if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
5315  return kUseCell;
5316  case LookupIterator::JSPROXY:
5317  case LookupIterator::TRANSITION:
5318  UNREACHABLE();
5319  }
5320  UNREACHABLE();
5321  return kUseGeneric;
5322 }

References v8::internal::ACCESSOR, current_info(), v8::internal::Variable::is_this(), kUseCell, kUseGeneric, v8::internal::STORE, and UNREACHABLE.

Referenced by HandleGlobalVariableAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ NewArgumentAdaptorCall()

HInstruction * v8::internal::HOptimizedGraphBuilder::NewArgumentAdaptorCall ( HValue fun,
HValue context,
int  argument_count,
HValue expected_param_count 
)
private

Definition at line 7437 of file hydrogen.cc.

7439  {
7440  ArgumentAdaptorDescriptor descriptor(isolate());
7441  HValue* arity = Add<HConstant>(argument_count - 1);
7442 
7443  HValue* op_vals[] = { context, fun, arity, expected_param_count };
7444 
7445  Handle<Code> adaptor =
7446  isolate()->builtins()->ArgumentsAdaptorTrampoline();
7447  HConstant* adaptor_value = Add<HConstant>(adaptor);
7448 
7449  return New<HCallWithDescriptor>(
7450  adaptor_value, argument_count, descriptor,
7451  Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
7452 }
Builtins * builtins()
Definition: isolate.h:947

References v8::internal::Isolate::builtins(), context(), v8::internal::CallInterfaceDescriptor::GetEnvironmentLength(), and v8::internal::HGraphBuilder::isolate().

Referenced by BuildCallConstantFunction().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ NewPlainFunctionCall()

HInstruction * v8::internal::HOptimizedGraphBuilder::NewPlainFunctionCall ( HValue fun,
int  argument_count,
bool  pass_argument_count 
)
private

Definition at line 7430 of file hydrogen.cc.

7431  {
7432  return New<HCallJSFunction>(
7433  fun, argument_count, pass_argument_count);
7434 }

Referenced by BuildCallConstantFunction().

+ Here is the caller graph for this function:

◆ operator delete() [1/2]

void v8::internal::HOptimizedGraphBuilder::operator delete ( void *  pointer)
inline

Definition at line 2131 of file hydrogen.h.

2131 { }

◆ operator delete() [2/2]

void v8::internal::HOptimizedGraphBuilder::operator delete ( void *  pointer,
Zone zone 
)
inline

Definition at line 2130 of file hydrogen.h.

2130 { }

◆ operator new()

void* v8::internal::HOptimizedGraphBuilder::operator new ( size_t  size,
Zone zone 
)
inline

Definition at line 2127 of file hydrogen.h.

2127  {
2128  return zone->New(static_cast<int>(size));
2129  }
void * New(int size)
Definition: zone.cc:65
enable harmony numeric enable harmony object literal extensions Optimize object size

References v8::internal::Zone::New(), size, and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ osr()

HOsrBuilder* v8::internal::HOptimizedGraphBuilder::osr ( ) const
inline

Definition at line 2115 of file hydrogen.h.

2115 { return osr_; }

References osr_.

Referenced by BuildGraph(), and BuildLoopEntry().

+ Here is the caller graph for this function:

◆ PreProcessCall()

template<class Instruction >
HInstruction * v8::internal::HOptimizedGraphBuilder::PreProcessCall ( Instruction call)
protected

Definition at line 4468 of file hydrogen.cc.

4468  {
4469  PushArgumentsFromEnvironment(call->argument_count());
4470  return call;
4471 }

References PushArgumentsFromEnvironment().

Referenced by BuildArrayCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PreProcessOsrEntry()

bool v8::internal::HOptimizedGraphBuilder::PreProcessOsrEntry ( IterationStatement statement)
protected

◆ PushArgumentsFromEnvironment()

void v8::internal::HOptimizedGraphBuilder::PushArgumentsFromEnvironment ( int  count)
protected

Definition at line 4453 of file hydrogen.cc.

4453  {
4454  ZoneList<HValue*> arguments(count, zone());
4455  for (int i = 0; i < count; ++i) {
4456  arguments.Add(Pop(), zone());
4457  }
4458 
4459  HPushArguments* push_args = New<HPushArguments>();
4460  while (!arguments.is_empty()) {
4461  push_args->AddInput(arguments.RemoveLast());
4462  }
4463  AddInstruction(push_args);
4464 }

References v8::internal::List< T, AllocationPolicy >::Add(), v8::internal::HGraphBuilder::AddInstruction(), v8::internal::HGraphBuilder::Pop(), and v8::internal::HGraphBuilder::zone().

Referenced by BuildMonomorphicAccess(), HandlePolymorphicCallNamed(), PreProcessCall(), TryCallApply(), and TryInlineApiCall().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PushLoad()

void v8::internal::HOptimizedGraphBuilder::PushLoad ( Property *  property,
HValue object,
HValue key 
)
private

Definition at line 7327 of file hydrogen.cc.

7329  {
7330  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7331  Push(object);
7332  if (key != NULL) Push(key);
7333  BuildLoad(expr, expr->LoadId());
7334 }
void BuildLoad(Property *property, BailoutId ast_id)
Definition: hydrogen.cc:7337
@ ARGUMENTS_NOT_ALLOWED
Definition: hydrogen.h:752

References v8::internal::ARGUMENTS_NOT_ALLOWED, BuildLoad(), NULL, and v8::internal::HGraphBuilder::Push().

Referenced by HandleCompoundAssignment().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_ast_context()

void v8::internal::HOptimizedGraphBuilder::set_ast_context ( AstContext context)
inlineprotected

Definition at line 2164 of file hydrogen.h.

2164 { ast_context_ = context; }

References ast_context_, and context().

Referenced by v8::internal::AstContext::AstContext(), and v8::internal::AstContext::~AstContext().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ set_break_scope()

void v8::internal::HOptimizedGraphBuilder::set_break_scope ( BreakAndContinueScope *  head)
inline

Definition at line 2111 of file hydrogen.h.

2111 { break_scope_ = head; }

References break_scope_.

Referenced by v8::internal::HOptimizedGraphBuilder::BASE_EMBEDDED::BreakAndContinueScope().

+ Here is the caller graph for this function:

◆ set_function_state()

void v8::internal::HOptimizedGraphBuilder::set_function_state ( FunctionState state)
inlineprotected

Definition at line 2161 of file hydrogen.h.

2161 { function_state_ = state; }

References function_state_.

◆ SetUpScope()

void v8::internal::HOptimizedGraphBuilder::SetUpScope ( Scope scope)
protected

Definition at line 4474 of file hydrogen.cc.

4474  {
4475  // First special is HContext.
4476  HInstruction* context = Add<HContext>();
4477  environment()->BindContext(context);
4478 
4479  // Create an arguments object containing the initial parameters. Set the
4480  // initial values of parameters including "this" having parameter index 0.
4481  DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
4482  HArgumentsObject* arguments_object =
4483  New<HArgumentsObject>(environment()->parameter_count());
4484  for (int i = 0; i < environment()->parameter_count(); ++i) {
4485  HInstruction* parameter = Add<HParameter>(i);
4486  arguments_object->AddArgument(parameter, zone());
4487  environment()->Bind(i, parameter);
4488  }
4489  AddInstruction(arguments_object);
4490  graph()->SetArgumentsObject(arguments_object);
4491 
4492  HConstant* undefined_constant = graph()->GetConstantUndefined();
4493  // Initialize specials and locals to undefined.
4494  for (int i = environment()->parameter_count() + 1;
4495  i < environment()->length();
4496  ++i) {
4497  environment()->Bind(i, undefined_constant);
4498  }
4499 
4500  // Handle the arguments and arguments shadow variables specially (they do
4501  // not have declarations).
4502  if (scope->arguments() != NULL) {
4503  if (!scope->arguments()->IsStackAllocated()) {
4504  return Bailout(kContextAllocatedArguments);
4505  }
4506 
4507  environment()->Bind(scope->arguments(),
4508  graph()->GetArgumentsObject());
4509  }
4510 }
Variable * arguments() const
Definition: scopes.h:324
bool IsStackAllocated() const
Definition: variables.h:96

References v8::internal::HGraphBuilder::AddInstruction(), v8::internal::Scope::arguments(), Bailout(), context(), DCHECK_EQ, v8::internal::HGraphBuilder::environment(), v8::internal::HGraphBuilder::graph(), v8::internal::Variable::IsStackAllocated(), NULL, v8::internal::Scope::num_parameters(), v8::internal::HGraphBuilder::scope(), and v8::internal::HGraphBuilder::zone().

Referenced by BuildGraph().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Top()

HValue* v8::internal::HOptimizedGraphBuilder::Top ( ) const
inlineprotected

Definition at line 2230 of file hydrogen.h.

2230 { return environment()->Top(); }

References v8::internal::HGraphBuilder::environment().

Referenced by BuildIncrement(), BuildInlinedCallArray(), HandleCompoundAssignment(), IsCallArrayInlineable(), TryInlineBuiltinMethodCall(), and VisitLogicalExpression().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ToType()

Type * v8::internal::HOptimizedGraphBuilder::ToType ( Handle< Map map)
protected

Definition at line 4513 of file hydrogen.cc.

4513  {
4514  return IC::MapToType<Type>(map, zone());
4515 }

References map, and v8::internal::HGraphBuilder::zone().

Referenced by BuildNamedAccess(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(), HandlePolymorphicCallNamed(), HandlePolymorphicNamedFieldAccess(), v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes(), and v8::internal::HOptimizedGraphBuilder::PropertyAccessInfo::ToType().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TraceInline()

void v8::internal::HOptimizedGraphBuilder::TraceInline ( Handle< JSFunction target,
Handle< JSFunction caller,
const char *  failure_reason 
)
private

Definition at line 7690 of file hydrogen.cc.

7692  {
7693  if (FLAG_trace_inlining) {
7694  SmartArrayPointer<char> target_name =
7695  target->shared()->DebugName()->ToCString();
7696  SmartArrayPointer<char> caller_name =
7697  caller->shared()->DebugName()->ToCString();
7698  if (reason == NULL) {
7699  PrintF("Inlined %s called from %s.\n", target_name.get(),
7700  caller_name.get());
7701  } else {
7702  PrintF("Did not inline %s called from %s (%s).\n",
7703  target_name.get(), caller_name.get(), reason);
7704  }
7705  }
7706 }

References v8::internal::SmartPointerBase< Deallocator, T >::get(), NULL, and v8::internal::PrintF().

Referenced by InliningAstSize(), IsCallArrayInlineable(), and TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryArgumentsAccess()

bool v8::internal::HOptimizedGraphBuilder::TryArgumentsAccess ( Property *  expr)
private

Definition at line 7237 of file hydrogen.cc.

7237  {
7238  VariableProxy* proxy = expr->obj()->AsVariableProxy();
7239  if (proxy == NULL) return false;
7240  if (!proxy->var()->IsStackAllocated()) return false;
7241  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7242  return false;
7243  }
7244 
7245  HInstruction* result = NULL;
7246  if (expr->key()->IsPropertyName()) {
7247  Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7248  if (!String::Equals(name, isolate()->factory()->length_string())) {
7249  return false;
7250  }
7251 
7252  if (function_state()->outer() == NULL) {
7253  HInstruction* elements = Add<HArgumentsElements>(false);
7254  result = New<HArgumentsLength>(elements);
7255  } else {
7256  // Number of arguments without receiver.
7257  int argument_count = environment()->
7258  arguments_environment()->parameter_count() - 1;
7259  result = New<HConstant>(argument_count);
7260  }
7261  } else {
7262  Push(graph()->GetArgumentsObject());
7263  CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
7264  HValue* key = Pop();
7265  Drop(1); // Arguments object.
7266  if (function_state()->outer() == NULL) {
7267  HInstruction* elements = Add<HArgumentsElements>(false);
7268  HInstruction* length = Add<HArgumentsLength>(elements);
7269  HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7270  result = New<HAccessArgumentsAt>(elements, length, checked_key);
7271  } else {
7273 
7274  // Number of arguments without receiver.
7275  HInstruction* elements = function_state()->arguments_elements();
7276  int argument_count = environment()->
7277  arguments_environment()->parameter_count() - 1;
7278  HInstruction* length = Add<HConstant>(argument_count);
7279  HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7280  result = New<HAccessArgumentsAt>(elements, length, checked_key);
7281  }
7282  }
7283  ast_context()->ReturnInstruction(result, expr->id());
7284  return true;
7285 }
bool Equals(String *other)
Definition: objects-inl.h:3336
#define CHECK_ALIVE_OR_RETURN(call, value)
Definition: hydrogen.cc:4205

References ast_context(), CHECK_ALIVE_OR_RETURN, Drop(), EnsureArgumentsArePushedForAccess(), v8::internal::HGraphBuilder::environment(), v8::internal::String::Equals(), function_state(), v8::internal::HGraphBuilder::graph(), v8::internal::HValue::id(), v8::internal::HGraphBuilder::isolate(), v8::internal::HValue::kIsArguments, name, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::AstContext::ReturnInstruction(), and VisitForValue().

+ Here is the call graph for this function:

◆ TryBuildConsolidatedElementLoad()

HInstruction * v8::internal::HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad ( HValue object,
HValue key,
HValue val,
SmallMapList *  maps 
)
private

Definition at line 6923 of file hydrogen.cc.

6927  {
6928  // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6929  // double), always use the "worst case" code without a transition. This is
6930  // much faster than transitioning the elements to the worst case, trading a
6931  // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
6932  bool has_double_maps = false;
6933  bool has_smi_or_object_maps = false;
6934  bool has_js_array_access = false;
6935  bool has_non_js_array_access = false;
6936  bool has_seen_holey_elements = false;
6937  Handle<Map> most_general_consolidated_map;
6938  for (int i = 0; i < maps->length(); ++i) {
6939  Handle<Map> map = maps->at(i);
6940  if (!map->IsJSObjectMap()) return NULL;
6941  // Don't allow mixing of JSArrays with JSObjects.
6942  if (map->instance_type() == JS_ARRAY_TYPE) {
6943  if (has_non_js_array_access) return NULL;
6944  has_js_array_access = true;
6945  } else if (has_js_array_access) {
6946  return NULL;
6947  } else {
6948  has_non_js_array_access = true;
6949  }
6950  // Don't allow mixed, incompatible elements kinds.
6951  if (map->has_fast_double_elements()) {
6952  if (has_smi_or_object_maps) return NULL;
6953  has_double_maps = true;
6954  } else if (map->has_fast_smi_or_object_elements()) {
6955  if (has_double_maps) return NULL;
6956  has_smi_or_object_maps = true;
6957  } else {
6958  return NULL;
6959  }
6960  // Remember if we've ever seen holey elements.
6961  if (IsHoleyElementsKind(map->elements_kind())) {
6962  has_seen_holey_elements = true;
6963  }
6964  // Remember the most general elements kind, the code for its load will
6965  // properly handle all of the more specific cases.
6966  if ((i == 0) || IsMoreGeneralElementsKindTransition(
6967  most_general_consolidated_map->elements_kind(),
6968  map->elements_kind())) {
6969  most_general_consolidated_map = map;
6970  }
6971  }
6972  if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6973 
6974  HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
6975  // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
6976  // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
6977  ElementsKind consolidated_elements_kind = has_seen_holey_elements
6978  ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
6979  : most_general_consolidated_map->elements_kind();
6980  HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6981  checked_object, key, val,
6982  most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6983  consolidated_elements_kind,
6985  return instr;
6986 }
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
@ STANDARD_STORE
Definition: objects.h:154

References v8::internal::HGraphBuilder::BuildUncheckedMonomorphicElementAccess(), v8::internal::GetHoleyElementsKind(), v8::internal::IsHoleyElementsKind(), v8::internal::IsMoreGeneralElementsKindTransition(), v8::internal::JS_ARRAY_TYPE, v8::internal::LOAD, map, v8::internal::NEVER_RETURN_HOLE, NULL, and v8::internal::STANDARD_STORE.

Referenced by HandlePolymorphicElementAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryCallApply()

bool v8::internal::HOptimizedGraphBuilder::TryCallApply ( Call *  expr)
private

Definition at line 8693 of file hydrogen.cc.

8693  {
8694  DCHECK(expr->expression()->IsProperty());
8695 
8696  if (!expr->IsMonomorphic()) {
8697  return false;
8698  }
8699  Handle<Map> function_map = expr->GetReceiverTypes()->first();
8700  if (function_map->instance_type() != JS_FUNCTION_TYPE ||
8701  !expr->target()->shared()->HasBuiltinFunctionId() ||
8702  expr->target()->shared()->builtin_function_id() != kFunctionApply) {
8703  return false;
8704  }
8705 
8706  if (current_info()->scope()->arguments() == NULL) return false;
8707 
8708  ZoneList<Expression*>* args = expr->arguments();
8709  if (args->length() != 2) return false;
8710 
8711  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
8712  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
8713  HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
8714  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
8715 
8716  // Found pattern f.apply(receiver, arguments).
8717  CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
8718  HValue* receiver = Pop(); // receiver
8719  HValue* function = Pop(); // f
8720  Drop(1); // apply
8721 
8722  HValue* checked_function = AddCheckMap(function, function_map);
8723 
8724  if (function_state()->outer() == NULL) {
8725  HInstruction* elements = Add<HArgumentsElements>(false);
8726  HInstruction* length = Add<HArgumentsLength>(elements);
8727  HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
8728  HInstruction* result = New<HApplyArguments>(function,
8729  wrapped_receiver,
8730  length,
8731  elements);
8732  ast_context()->ReturnInstruction(result, expr->id());
8733  return true;
8734  } else {
8735  // We are inside inlined function and we know exactly what is inside
8736  // arguments object. But we need to be able to materialize at deopt.
8737  DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
8738  function_state()->entry()->arguments_object()->arguments_count());
8739  HArgumentsObject* args = function_state()->entry()->arguments_object();
8740  const ZoneList<HValue*>* arguments_values = args->arguments_values();
8741  int arguments_count = arguments_values->length();
8742  Push(function);
8743  Push(BuildWrapReceiver(receiver, checked_function));
8744  for (int i = 1; i < arguments_count; i++) {
8745  Push(arguments_values->at(i));
8746  }
8747 
8748  Handle<JSFunction> known_function;
8749  if (function->IsConstant() &&
8750  HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8751  known_function = Handle<JSFunction>::cast(
8752  HConstant::cast(function)->handle(isolate()));
8753  int args_count = arguments_count - 1; // Excluding receiver.
8754  if (TryInlineApply(known_function, expr, args_count)) return true;
8755  }
8756 
8757  PushArgumentsFromEnvironment(arguments_count);
8758  HInvokeFunction* call = New<HInvokeFunction>(
8759  function, known_function, arguments_count);
8760  Drop(1); // Function.
8761  ast_context()->ReturnInstruction(call, expr->id());
8762  return true;
8763  }
8764 }
HValue * BuildWrapReceiver(HValue *object, HValue *function)
Definition: hydrogen.cc:1289
bool TryInlineApply(Handle< JSFunction > function, Call *expr, int arguments_count)
Definition: hydrogen.cc:8085
HValue * LookupAndMakeLive(Variable *var)
Definition: hydrogen.h:2259
@ JS_FUNCTION_TYPE
Definition: objects.h:749

References AddCheckMap(), ast_context(), v8::internal::List< T, AllocationPolicy >::at(), v8::internal::HGraphBuilder::BuildWrapReceiver(), v8::internal::Handle< T >::cast(), CHECK_ALIVE_OR_RETURN, v8::internal::HValue::CheckFlag(), current_info(), DCHECK, DCHECK_EQ, Drop(), v8::internal::HGraphBuilder::environment(), function_state(), v8::internal::handle(), v8::internal::HValue::id(), v8::internal::HGraphBuilder::isolate(), v8::internal::JS_FUNCTION_TYPE, v8::internal::HValue::kIsArguments, LookupAndMakeLive(), NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), PushArgumentsFromEnvironment(), v8::internal::AstContext::ReturnInstruction(), v8::internal::HGraphBuilder::scope(), TryInlineApply(), and VisitForValue().

+ Here is the call graph for this function:

◆ TryHandleArrayCall()

bool v8::internal::HOptimizedGraphBuilder::TryHandleArrayCall ( Call *  expr,
HValue function 
)
private

Definition at line 8952 of file hydrogen.cc.

8952  {
8953  if (!array_function().is_identical_to(expr->target())) {
8954  return false;
8955  }
8956 
8957  Handle<AllocationSite> site = expr->allocation_site();
8958  if (site.is_null()) return false;
8959 
8960  BuildArrayCall(expr,
8961  expr->arguments()->length(),
8962  function,
8963  site);
8964  return true;
8965 }
void BuildArrayCall(Expression *expr, int arguments_count, HValue *function, Handle< AllocationSite > cell)
Definition: hydrogen.cc:8781

References array_function(), BuildArrayCall(), and v8::internal::Handle< T >::is_null().

+ Here is the call graph for this function:

◆ TryHandleArrayCallNew()

bool v8::internal::HOptimizedGraphBuilder::TryHandleArrayCallNew ( CallNew *  expr,
HValue function 
)
private

Definition at line 8968 of file hydrogen.cc.

8969  {
8970  if (!array_function().is_identical_to(expr->target())) {
8971  return false;
8972  }
8973 
8974  BuildArrayCall(expr,
8975  expr->arguments()->length(),
8976  function,
8977  expr->allocation_site());
8978  return true;
8979 }

References array_function(), and BuildArrayCall().

+ Here is the call graph for this function:

◆ TryInline()

bool v8::internal::HOptimizedGraphBuilder::TryInline ( Handle< JSFunction target,
int  arguments_count,
HValue implicit_return_value,
BailoutId  ast_id,
BailoutId  return_id,
InliningKind  inlining_kind,
HSourcePosition  position 
)
private

Definition at line 7753 of file hydrogen.cc.

7759  {
7760  int nodes_added = InliningAstSize(target);
7761  if (nodes_added == kNotInlinable) return false;
7762 
7763  Handle<JSFunction> caller = current_info()->closure();
7764 
7765  if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7766  TraceInline(target, caller, "target AST is too large [early]");
7767  return false;
7768  }
7769 
7770  // Don't inline deeper than the maximum number of inlining levels.
7771  HEnvironment* env = environment();
7772  int current_level = 1;
7773  while (env->outer() != NULL) {
7774  if (current_level == FLAG_max_inlining_levels) {
7775  TraceInline(target, caller, "inline depth limit reached");
7776  return false;
7777  }
7778  if (env->outer()->frame_type() == JS_FUNCTION) {
7779  current_level++;
7780  }
7781  env = env->outer();
7782  }
7783 
7784  // Don't inline recursive functions.
7785  for (FunctionState* state = function_state();
7786  state != NULL;
7787  state = state->outer()) {
7788  if (*state->compilation_info()->closure() == *target) {
7789  TraceInline(target, caller, "target is recursive");
7790  return false;
7791  }
7792  }
7793 
7794  // We don't want to add more than a certain number of nodes from inlining.
7795  if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
7797  TraceInline(target, caller, "cumulative AST node limit reached");
7798  return false;
7799  }
7800 
7801  // Parse and allocate variables.
7802  CompilationInfo target_info(target, zone());
7803  // Use the same AstValueFactory for creating strings in the sub-compilation
7804  // step, but don't transfer ownership to target_info.
7805  target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
7806  Handle<SharedFunctionInfo> target_shared(target->shared());
7807  if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
7808  if (target_info.isolate()->has_pending_exception()) {
7809  // Parse or scope error, never optimize this function.
7810  SetStackOverflow();
7811  target_shared->DisableOptimization(kParseScopeError);
7812  }
7813  TraceInline(target, caller, "parse failure");
7814  return false;
7815  }
7816 
7817  if (target_info.scope()->num_heap_slots() > 0) {
7818  TraceInline(target, caller, "target has context-allocated variables");
7819  return false;
7820  }
7821  FunctionLiteral* function = target_info.function();
7822 
7823  // The following conditions must be checked again after re-parsing, because
7824  // earlier the information might not have been complete due to lazy parsing.
7825  nodes_added = function->ast_node_count();
7826  if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7827  TraceInline(target, caller, "target AST is too large [late]");
7828  return false;
7829  }
7830  if (function->dont_optimize()) {
7831  TraceInline(target, caller, "target contains unsupported syntax [late]");
7832  return false;
7833  }
7834 
7835  // If the function uses the arguments object check that inlining of functions
7836  // with arguments object is enabled and the arguments-variable is
7837  // stack allocated.
7838  if (function->scope()->arguments() != NULL) {
7839  if (!FLAG_inline_arguments) {
7840  TraceInline(target, caller, "target uses arguments object");
7841  return false;
7842  }
7843 
7844  if (!function->scope()->arguments()->IsStackAllocated()) {
7845  TraceInline(target,
7846  caller,
7847  "target uses non-stackallocated arguments object");
7848  return false;
7849  }
7850  }
7851 
7852  // All declarations must be inlineable.
7853  ZoneList<Declaration*>* decls = target_info.scope()->declarations();
7854  int decl_count = decls->length();
7855  for (int i = 0; i < decl_count; ++i) {
7856  if (!decls->at(i)->IsInlineable()) {
7857  TraceInline(target, caller, "target has non-trivial declaration");
7858  return false;
7859  }
7860  }
7861 
7862  // Generate the deoptimization data for the unoptimized version of
7863  // the target function if we don't already have it.
7864  if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
7865  TraceInline(target, caller, "could not generate deoptimization info");
7866  return false;
7867  }
7868 
7869  // ----------------------------------------------------------------
7870  // After this point, we've made a decision to inline this function (so
7871  // TryInline should always return true).
7872 
7873  // Type-check the inlined function.
7874  DCHECK(target_shared->has_deoptimization_support());
7875  AstTyper::Run(&target_info);
7876 
7877  int function_id = graph()->TraceInlinedFunction(target_shared, position);
7878 
7879  // Save the pending call context. Set up new one for the inlined function.
7880  // The function state is new-allocated because we need to delete it
7881  // in two different places.
7882  FunctionState* target_state = new FunctionState(
7883  this, &target_info, inlining_kind, function_id);
7884 
7885  HConstant* undefined = graph()->GetConstantUndefined();
7886 
7887  HEnvironment* inner_env =
7888  environment()->CopyForInlining(target,
7889  arguments_count,
7890  function,
7891  undefined,
7892  function_state()->inlining_kind());
7893 
7894  HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
7895  inner_env->BindContext(context);
7896 
7897  // Create a dematerialized arguments object for the function, also copy the
7898  // current arguments values to use them for materialization.
7899  HEnvironment* arguments_env = inner_env->arguments_environment();
7900  int parameter_count = arguments_env->parameter_count();
7901  HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
7902  for (int i = 0; i < parameter_count; i++) {
7903  arguments_object->AddArgument(arguments_env->Lookup(i), zone());
7904  }
7905 
7906  // If the function uses arguments object then bind bind one.
7907  if (function->scope()->arguments() != NULL) {
7908  DCHECK(function->scope()->arguments()->IsStackAllocated());
7909  inner_env->Bind(function->scope()->arguments(), arguments_object);
7910  }
7911 
7912  // Capture the state before invoking the inlined function for deopt in the
7913  // inlined function. This simulate has no bailout-id since it's not directly
7914  // reachable for deopt, and is only used to capture the state. If the simulate
7915  // becomes reachable by merging, the ast id of the simulate merged into it is
7916  // adopted.
7917  Add<HSimulate>(BailoutId::None());
7918 
7919  current_block()->UpdateEnvironment(inner_env);
7920  Scope* saved_scope = scope();
7921  set_scope(target_info.scope());
7922  HEnterInlined* enter_inlined =
7923  Add<HEnterInlined>(return_id, target, context, arguments_count, function,
7924  function_state()->inlining_kind(),
7925  function->scope()->arguments(), arguments_object);
7926  function_state()->set_entry(enter_inlined);
7927 
7928  VisitDeclarations(target_info.scope()->declarations());
7929  VisitStatements(function->body());
7930  set_scope(saved_scope);
7931  if (HasStackOverflow()) {
7932  // Bail out if the inline function did, as we cannot residualize a call
7933  // instead, but do not disable optimization for the outer function.
7934  TraceInline(target, caller, "inline graph construction failed");
7935  target_shared->DisableOptimization(kInliningBailedOut);
7936  current_info()->RetryOptimization(kInliningBailedOut);
7937  delete target_state;
7938  return true;
7939  }
7940 
7941  // Update inlined nodes count.
7942  inlined_count_ += nodes_added;
7943 
7944  Handle<Code> unoptimized_code(target_shared->code());
7945  DCHECK(unoptimized_code->kind() == Code::FUNCTION);
7946  Handle<TypeFeedbackInfo> type_info(
7947  TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
7948  graph()->update_type_change_checksum(type_info->own_type_change_checksum());
7949 
7950  TraceInline(target, caller, NULL);
7951 
7952  if (current_block() != NULL) {
7953  FunctionState* state = function_state();
7954  if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
7955  // Falling off the end of an inlined construct call. In a test context the
7956  // return value will always evaluate to true, in a value context the
7957  // return value is the newly allocated receiver.
7958  if (call_context()->IsTest()) {
7959  Goto(inlined_test_context()->if_true(), state);
7960  } else if (call_context()->IsEffect()) {
7961  Goto(function_return(), state);
7962  } else {
7963  DCHECK(call_context()->IsValue());
7964  AddLeaveInlined(implicit_return_value, state);
7965  }
7966  } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
7967  // Falling off the end of an inlined setter call. The returned value is
7968  // never used, the value of an assignment is always the value of the RHS
7969  // of the assignment.
7970  if (call_context()->IsTest()) {
7971  inlined_test_context()->ReturnValue(implicit_return_value);
7972  } else if (call_context()->IsEffect()) {
7973  Goto(function_return(), state);
7974  } else {
7975  DCHECK(call_context()->IsValue());
7976  AddLeaveInlined(implicit_return_value, state);
7977  }
7978  } else {
7979  // Falling off the end of a normal inlined function. This basically means
7980  // returning undefined.
7981  if (call_context()->IsTest()) {
7982  Goto(inlined_test_context()->if_false(), state);
7983  } else if (call_context()->IsEffect()) {
7984  Goto(function_return(), state);
7985  } else {
7986  DCHECK(call_context()->IsValue());
7987  AddLeaveInlined(undefined, state);
7988  }
7989  }
7990  }
7991 
7992  // Fix up the function exits.
7993  if (inlined_test_context() != NULL) {
7994  HBasicBlock* if_true = inlined_test_context()->if_true();
7995  HBasicBlock* if_false = inlined_test_context()->if_false();
7996 
7997  HEnterInlined* entry = function_state()->entry();
7998 
7999  // Pop the return test context from the expression context stack.
8002  delete target_state;
8003 
8004  // Forward to the real test context.
8005  if (if_true->HasPredecessor()) {
8006  entry->RegisterReturnTarget(if_true, zone());
8007  if_true->SetJoinId(ast_id);
8008  HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
8009  Goto(if_true, true_target, function_state());
8010  }
8011  if (if_false->HasPredecessor()) {
8012  entry->RegisterReturnTarget(if_false, zone());
8013  if_false->SetJoinId(ast_id);
8014  HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
8015  Goto(if_false, false_target, function_state());
8016  }
8018  return true;
8019 
8020  } else if (function_return()->HasPredecessor()) {
8021  function_state()->entry()->RegisterReturnTarget(function_return(), zone());
8022  function_return()->SetJoinId(ast_id);
8024  } else {
8026  }
8027  delete target_state;
8028  return true;
8029 }
static void Run(CompilationInfo *info)
Definition: typing.cc:36
static BailoutId None()
Definition: utils.h:960
void RetryOptimization(BailoutReason reason)
Definition: compiler.h:335
static bool EnsureDeoptimizationSupport(CompilationInfo *info)
Definition: compiler.cc:895
void set_scope(Scope *scope)
Definition: hydrogen.h:1055
void AddLeaveInlined(HBasicBlock *block, HValue *return_value, FunctionState *state)
Definition: hydrogen.h:1097
static const int kUnlimitedMaxInlinedNodes
Definition: hydrogen.h:2152
TestContext * inlined_test_context() const
Definition: hydrogen.h:2176
AstContext * call_context() const
Definition: hydrogen.h:2170
static const int kUnlimitedMaxInlinedNodesCumulative
Definition: hydrogen.h:2153
HBasicBlock * function_return() const
Definition: hydrogen.h:2173
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:260

References v8::internal::HGraphBuilder::AddLeaveInlined(), v8::internal::Scope::Analyze(), ast_context(), v8::internal::List< T, AllocationPolicy >::at(), call_context(), ClearInlinedTestContext(), v8::internal::CompilationInfo::closure(), v8::internal::CONSTRUCT_CALL_RETURN, context(), v8::internal::HGraphBuilder::current_block(), current_info(), DCHECK, v8::internal::Scope::declarations(), v8::internal::Compiler::EnsureDeoptimizationSupport(), v8::internal::HGraphBuilder::environment(), v8::internal::CompilationInfo::function(), function_return(), function_state(), FunctionState, v8::internal::HGraphBuilder::Goto(), v8::internal::HGraphBuilder::graph(), v8::internal::Isolate::has_pending_exception(), inlined_count_, inlined_test_context(), InliningAstSize(), v8::internal::CompilationInfo::isolate(), v8::internal::JS_FUNCTION, v8::internal::kNotInlinable, kUnlimitedMaxInlinedNodes, kUnlimitedMaxInlinedNodesCumulative, v8::internal::Min(), v8::internal::BailoutId::None(), NULL, v8::internal::Scope::num_heap_slots(), v8::internal::Parser::Parse(), v8::internal::CompilationInfo::RetryOptimization(), v8::internal::AstTyper::Run(), v8::internal::CompilationInfo::scope(), v8::internal::HGraphBuilder::scope(), v8::internal::HGraphBuilder::set_current_block(), v8::internal::HGraphBuilder::set_scope(), v8::internal::CompilationInfo::SetAstValueFactory(), v8::internal::SETTER_CALL_RETURN, v8::internal::HGraphBuilder::top_info(), TraceInline(), VisitDeclarations(), VisitStatements(), and v8::internal::HGraphBuilder::zone().

Referenced by TryInlineApply(), TryInlineCall(), TryInlineConstruct(), TryInlineGetter(), and TryInlineSetter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineApiCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApiCall ( Handle< JSFunction function,
HValue receiver,
SmallMapList *  receiver_maps,
int  argc,
BailoutId  ast_id,
ApiCallType  call_type 
)
private

Definition at line 8578 of file hydrogen.cc.

8583  {
8584  CallOptimization optimization(function);
8585  if (!optimization.is_simple_api_call()) return false;
8586  Handle<Map> holder_map;
8587  if (call_type == kCallApiFunction) {
8588  // Cannot embed a direct reference to the global proxy map
8589  // as it maybe dropped on deserialization.
8590  CHECK(!isolate()->serializer_enabled());
8591  DCHECK_EQ(0, receiver_maps->length());
8592  receiver_maps->Add(handle(function->global_proxy()->map()), zone());
8593  }
8594  CallOptimization::HolderLookup holder_lookup =
8595  CallOptimization::kHolderNotFound;
8596  Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
8597  receiver_maps->first(), &holder_lookup);
8598  if (holder_lookup == CallOptimization::kHolderNotFound) return false;
8599 
8600  if (FLAG_trace_inlining) {
8601  PrintF("Inlining api function ");
8602  function->ShortPrint();
8603  PrintF("\n");
8604  }
8605 
8606  bool drop_extra = false;
8607  bool is_store = false;
8608  switch (call_type) {
8609  case kCallApiFunction:
8610  case kCallApiMethod:
8611  // Need to check that none of the receiver maps could have changed.
8612  Add<HCheckMaps>(receiver, receiver_maps);
8613  // Need to ensure the chain between receiver and api_holder is intact.
8614  if (holder_lookup == CallOptimization::kHolderFound) {
8615  AddCheckPrototypeMaps(api_holder, receiver_maps->first());
8616  } else {
8617  DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
8618  }
8619  // Includes receiver.
8620  PushArgumentsFromEnvironment(argc + 1);
8621  // Drop function after call.
8622  drop_extra = true;
8623  break;
8624  case kCallApiGetter:
8625  // Receiver and prototype chain cannot have changed.
8626  DCHECK_EQ(0, argc);
8627  DCHECK_EQ(NULL, receiver);
8628  // Receiver is on expression stack.
8629  receiver = Pop();
8630  Add<HPushArguments>(receiver);
8631  break;
8632  case kCallApiSetter:
8633  {
8634  is_store = true;
8635  // Receiver and prototype chain cannot have changed.
8636  DCHECK_EQ(1, argc);
8637  DCHECK_EQ(NULL, receiver);
8638  // Receiver and value are on expression stack.
8639  HValue* value = Pop();
8640  receiver = Pop();
8641  Add<HPushArguments>(receiver, value);
8642  break;
8643  }
8644  }
8645 
8646  HValue* holder = NULL;
8647  switch (holder_lookup) {
8648  case CallOptimization::kHolderFound:
8649  holder = Add<HConstant>(api_holder);
8650  break;
8651  case CallOptimization::kHolderIsReceiver:
8652  holder = receiver;
8653  break;
8654  case CallOptimization::kHolderNotFound:
8655  UNREACHABLE();
8656  break;
8657  }
8658  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
8659  Handle<Object> call_data_obj(api_call_info->data(), isolate());
8660  bool call_data_is_undefined = call_data_obj->IsUndefined();
8661  HValue* call_data = Add<HConstant>(call_data_obj);
8662  ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8663  ExternalReference ref = ExternalReference(&fun,
8664  ExternalReference::DIRECT_API_CALL,
8665  isolate());
8666  HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8667 
8668  HValue* op_vals[] = {
8669  context(),
8670  Add<HConstant>(function),
8671  call_data,
8672  holder,
8673  api_function_address
8674  };
8675 
8676  ApiFunctionDescriptor descriptor(isolate());
8677  CallApiFunctionStub stub(isolate(), is_store, call_data_is_undefined, argc);
8678  Handle<Code> code = stub.GetCode();
8679  HConstant* code_value = Add<HConstant>(code);
8680 
8681  DCHECK((sizeof(op_vals) / kPointerSize) == descriptor.GetEnvironmentLength());
8682 
8683  HInstruction* call = New<HCallWithDescriptor>(
8684  code_value, argc + 1, descriptor,
8685  Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
8686 
8687  if (drop_extra) Drop(1); // Drop function.
8688  ast_context()->ReturnInstruction(call, ast_id);
8689  return true;
8690 }
const int kPointerSize
Definition: globals.h:129

References AddCheckPrototypeMaps(), ast_context(), CHECK, context(), DCHECK, DCHECK_EQ, Drop(), v8::internal::CallInterfaceDescriptor::GetEnvironmentLength(), v8::internal::handle(), v8::internal::HGraphBuilder::isolate(), kCallApiFunction, kCallApiGetter, kCallApiMethod, kCallApiSetter, v8::internal::kPointerSize, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::PrintF(), PushArgumentsFromEnvironment(), v8::internal::AstContext::ReturnInstruction(), UNREACHABLE, and v8::internal::HGraphBuilder::zone().

Referenced by TryInlineApiFunctionCall(), TryInlineApiGetter(), TryInlineApiMethodCall(), and TryInlineApiSetter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineApiFunctionCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApiFunctionCall ( Call *  expr,
HValue receiver 
)
private

Definition at line 8521 of file hydrogen.cc.

8522  {
8523  Handle<JSFunction> function = expr->target();
8524  int argc = expr->arguments()->length();
8525  SmallMapList receiver_maps;
8526  return TryInlineApiCall(function,
8527  receiver,
8528  &receiver_maps,
8529  argc,
8530  expr->id(),
8532 }
bool TryInlineApiCall(Handle< JSFunction > function, HValue *receiver, SmallMapList *receiver_maps, int argc, BailoutId ast_id, ApiCallType call_type)
Definition: hydrogen.cc:8578

References kCallApiFunction, and TryInlineApiCall().

+ Here is the call graph for this function:

◆ TryInlineApiGetter()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApiGetter ( Handle< JSFunction function,
Handle< Map receiver_map,
BailoutId  ast_id 
)
private

Definition at line 8550 of file hydrogen.cc.

8552  {
8553  SmallMapList receiver_maps(1, zone());
8554  receiver_maps.Add(receiver_map, zone());
8555  return TryInlineApiCall(function,
8556  NULL, // Receiver is on expression stack.
8557  &receiver_maps,
8558  0,
8559  ast_id,
8560  kCallApiGetter);
8561 }

References kCallApiGetter, NULL, TryInlineApiCall(), and v8::internal::HGraphBuilder::zone().

Referenced by TryInlineGetter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineApiMethodCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApiMethodCall ( Call *  expr,
HValue receiver,
SmallMapList *  receiver_types 
)
private

Definition at line 8535 of file hydrogen.cc.

8538  {
8539  Handle<JSFunction> function = expr->target();
8540  int argc = expr->arguments()->length();
8541  return TryInlineApiCall(function,
8542  receiver,
8543  receiver_maps,
8544  argc,
8545  expr->id(),
8546  kCallApiMethod);
8547 }

References kCallApiMethod, and TryInlineApiCall().

+ Here is the call graph for this function:

◆ TryInlineApiSetter()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApiSetter ( Handle< JSFunction function,
Handle< Map receiver_map,
BailoutId  ast_id 
)
private

Definition at line 8564 of file hydrogen.cc.

8566  {
8567  SmallMapList receiver_maps(1, zone());
8568  receiver_maps.Add(receiver_map, zone());
8569  return TryInlineApiCall(function,
8570  NULL, // Receiver is on expression stack.
8571  &receiver_maps,
8572  1,
8573  ast_id,
8574  kCallApiSetter);
8575 }

References kCallApiSetter, NULL, TryInlineApiCall(), and v8::internal::HGraphBuilder::zone().

Referenced by TryInlineSetter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineApply()

bool v8::internal::HOptimizedGraphBuilder::TryInlineApply ( Handle< JSFunction function,
Call *  expr,
int  arguments_count 
)
private

Definition at line 8085 of file hydrogen.cc.

8087  {
8088  return TryInline(function,
8089  arguments_count,
8090  NULL,
8091  expr->id(),
8092  expr->ReturnId(),
8093  NORMAL_RETURN,
8094  ScriptPositionToSourcePosition(expr->position()));
8095 }
HSourcePosition ScriptPositionToSourcePosition(int position)
Definition: hydrogen.h:1897
bool TryInline(Handle< JSFunction > target, int arguments_count, HValue *implicit_return_value, BailoutId ast_id, BailoutId return_id, InliningKind inlining_kind, HSourcePosition position)
Definition: hydrogen.cc:7753

References v8::internal::NORMAL_RETURN, NULL, v8::internal::HGraphBuilder::ScriptPositionToSourcePosition(), and TryInline().

Referenced by TryCallApply().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineBuiltinFunctionCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall ( Call *  expr)
private

Definition at line 8098 of file hydrogen.cc.

8098  {
8099  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8100  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8101  switch (id) {
8102  case kMathExp:
8103  if (!FLAG_fast_math) break;
8104  // Fall through if FLAG_fast_math.
8105  case kMathRound:
8106  case kMathFround:
8107  case kMathFloor:
8108  case kMathAbs:
8109  case kMathSqrt:
8110  case kMathLog:
8111  case kMathClz32:
8112  if (expr->arguments()->length() == 1) {
8113  HValue* argument = Pop();
8114  Drop(2); // Receiver and function.
8115  HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8116  ast_context()->ReturnInstruction(op, expr->id());
8117  return true;
8118  }
8119  break;
8120  case kMathImul:
8121  if (expr->arguments()->length() == 2) {
8122  HValue* right = Pop();
8123  HValue* left = Pop();
8124  Drop(2); // Receiver and function.
8125  HInstruction* op = HMul::NewImul(zone(), context(), left, right);
8126  ast_context()->ReturnInstruction(op, expr->id());
8127  return true;
8128  }
8129  break;
8130  default:
8131  // Not supported for inlining yet.
8132  break;
8133  }
8134  return false;
8135 }

References ast_context(), context(), Drop(), v8::internal::HValue::id(), v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnInstruction(), and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ TryInlineBuiltinMethodCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineBuiltinMethodCall ( Call *  expr,
HValue receiver,
Handle< Map receiver_map 
)
private

Definition at line 8138 of file hydrogen.cc.

8141  {
8142  // Try to inline calls like Math.* as operations in the calling function.
8143  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8144  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8145  int argument_count = expr->arguments()->length() + 1; // Plus receiver.
8146  switch (id) {
8147  case kStringCharCodeAt:
8148  case kStringCharAt:
8149  if (argument_count == 2) {
8150  HValue* index = Pop();
8151  HValue* string = Pop();
8152  Drop(1); // Function.
8153  HInstruction* char_code =
8154  BuildStringCharCodeAt(string, index);
8155  if (id == kStringCharCodeAt) {
8156  ast_context()->ReturnInstruction(char_code, expr->id());
8157  return true;
8158  }
8159  AddInstruction(char_code);
8160  HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8161  ast_context()->ReturnInstruction(result, expr->id());
8162  return true;
8163  }
8164  break;
8165  case kStringFromCharCode:
8166  if (argument_count == 2) {
8167  HValue* argument = Pop();
8168  Drop(2); // Receiver and function.
8169  HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8170  ast_context()->ReturnInstruction(result, expr->id());
8171  return true;
8172  }
8173  break;
8174  case kMathExp:
8175  if (!FLAG_fast_math) break;
8176  // Fall through if FLAG_fast_math.
8177  case kMathRound:
8178  case kMathFround:
8179  case kMathFloor:
8180  case kMathAbs:
8181  case kMathSqrt:
8182  case kMathLog:
8183  case kMathClz32:
8184  if (argument_count == 2) {
8185  HValue* argument = Pop();
8186  Drop(2); // Receiver and function.
8187  HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8188  ast_context()->ReturnInstruction(op, expr->id());
8189  return true;
8190  }
8191  break;
8192  case kMathPow:
8193  if (argument_count == 3) {
8194  HValue* right = Pop();
8195  HValue* left = Pop();
8196  Drop(2); // Receiver and function.
8197  HInstruction* result = NULL;
8198  // Use sqrt() if exponent is 0.5 or -0.5.
8199  if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8200  double exponent = HConstant::cast(right)->DoubleValue();
8201  if (exponent == 0.5) {
8202  result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8203  } else if (exponent == -0.5) {
8204  HValue* one = graph()->GetConstant1();
8205  HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8206  left, kMathPowHalf);
8207  // MathPowHalf doesn't have side effects so there's no need for
8208  // an environment simulation here.
8209  DCHECK(!sqrt->HasObservableSideEffects());
8210  result = NewUncasted<HDiv>(one, sqrt);
8211  } else if (exponent == 2.0) {
8212  result = NewUncasted<HMul>(left, left);
8213  }
8214  }
8215 
8216  if (result == NULL) {
8217  result = NewUncasted<HPower>(left, right);
8218  }
8219  ast_context()->ReturnInstruction(result, expr->id());
8220  return true;
8221  }
8222  break;
8223  case kMathMax:
8224  case kMathMin:
8225  if (argument_count == 3) {
8226  HValue* right = Pop();
8227  HValue* left = Pop();
8228  Drop(2); // Receiver and function.
8229  HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8230  : HMathMinMax::kMathMax;
8231  HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8232  ast_context()->ReturnInstruction(result, expr->id());
8233  return true;
8234  }
8235  break;
8236  case kMathImul:
8237  if (argument_count == 3) {
8238  HValue* right = Pop();
8239  HValue* left = Pop();
8240  Drop(2); // Receiver and function.
8241  HInstruction* result = HMul::NewImul(zone(), context(), left, right);
8242  ast_context()->ReturnInstruction(result, expr->id());
8243  return true;
8244  }
8245  break;
8246  case kArrayPop: {
8247  if (receiver_map.is_null()) return false;
8248  if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8249  ElementsKind elements_kind = receiver_map->elements_kind();
8250  if (!IsFastElementsKind(elements_kind)) return false;
8251  if (receiver_map->is_observed()) return false;
8252  if (!receiver_map->is_extensible()) return false;
8253 
8254  Drop(expr->arguments()->length());
8255  HValue* result;
8256  HValue* reduced_length;
8257  HValue* receiver = Pop();
8258 
8259  HValue* checked_object = AddCheckMap(receiver, receiver_map);
8260  HValue* length = Add<HLoadNamedField>(
8261  checked_object, static_cast<HValue*>(NULL),
8262  HObjectAccess::ForArrayLength(elements_kind));
8263 
8264  Drop(1); // Function.
8265 
8266  { NoObservableSideEffectsScope scope(this);
8267  IfBuilder length_checker(this);
8268 
8269  HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8270  length, graph()->GetConstant0(), Token::EQ);
8271  length_checker.Then();
8272 
8273  if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8274 
8275  length_checker.Else();
8276  HValue* elements = AddLoadElements(checked_object);
8277  // Ensure that we aren't popping from a copy-on-write array.
8278  if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8279  elements = BuildCopyElementsOnWrite(checked_object, elements,
8280  elements_kind, length);
8281  }
8282  reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
8283  result = AddElementAccess(elements, reduced_length, NULL,
8284  bounds_check, elements_kind, LOAD);
8285  Factory* factory = isolate()->factory();
8286  double nan_double = FixedDoubleArray::hole_nan_as_double();
8287  HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
8288  ? Add<HConstant>(factory->the_hole_value())
8289  : Add<HConstant>(nan_double);
8290  if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8291  elements_kind = FAST_HOLEY_ELEMENTS;
8292  }
8294  elements, reduced_length, hole, bounds_check, elements_kind, STORE);
8295  Add<HStoreNamedField>(
8296  checked_object, HObjectAccess::ForArrayLength(elements_kind),
8297  reduced_length, STORE_TO_INITIALIZED_ENTRY);
8298 
8299  if (!ast_context()->IsEffect()) Push(result);
8300 
8301  length_checker.End();
8302  }
8303  result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8304  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8305  if (!ast_context()->IsEffect()) Drop(1);
8306 
8307  ast_context()->ReturnValue(result);
8308  return true;
8309  }
8310  case kArrayPush: {
8311  if (receiver_map.is_null()) return false;
8312  if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8313  ElementsKind elements_kind = receiver_map->elements_kind();
8314  if (!IsFastElementsKind(elements_kind)) return false;
8315  if (receiver_map->is_observed()) return false;
8316  if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false;
8317  if (!receiver_map->is_extensible()) return false;
8318 
8319  // If there may be elements accessors in the prototype chain, the fast
8320  // inlined version can't be used.
8321  if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8322  // If there currently can be no elements accessors on the prototype chain,
8323  // it doesn't mean that there won't be any later. Install a full prototype
8324  // chain check to trap element accessors being installed on the prototype
8325  // chain, which would cause elements to go to dictionary mode and result
8326  // in a map change.
8327  Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8328  BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8329 
8330  const int argc = expr->arguments()->length();
8331  if (argc != 1) return false;
8332 
8333  HValue* value_to_push = Pop();
8334  HValue* array = Pop();
8335  Drop(1); // Drop function.
8336 
8337  HInstruction* new_size = NULL;
8338  HValue* length = NULL;
8339 
8340  {
8341  NoObservableSideEffectsScope scope(this);
8342 
8343  length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL),
8344  HObjectAccess::ForArrayLength(elements_kind));
8345 
8346  new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
8347 
8348  bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
8350  value_to_push, is_array,
8351  elements_kind, STORE,
8354 
8355  if (!ast_context()->IsEffect()) Push(new_size);
8356  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8357  if (!ast_context()->IsEffect()) Drop(1);
8358  }
8359 
8360  ast_context()->ReturnValue(new_size);
8361  return true;
8362  }
8363  case kArrayShift: {
8364  if (receiver_map.is_null()) return false;
8365  if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8366  ElementsKind kind = receiver_map->elements_kind();
8367  if (!IsFastElementsKind(kind)) return false;
8368  if (receiver_map->is_observed()) return false;
8369  if (!receiver_map->is_extensible()) return false;
8370 
8371  // If there may be elements accessors in the prototype chain, the fast
8372  // inlined version can't be used.
8373  if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8374 
8375  // If there currently can be no elements accessors on the prototype chain,
8376  // it doesn't mean that there won't be any later. Install a full prototype
8377  // chain check to trap element accessors being installed on the prototype
8378  // chain, which would cause elements to go to dictionary mode and result
8379  // in a map change.
8381  handle(JSObject::cast(receiver_map->prototype()), isolate()),
8383 
8384  // Threshold for fast inlined Array.shift().
8385  HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8386 
8387  Drop(expr->arguments()->length());
8388  HValue* receiver = Pop();
8389  HValue* function = Pop();
8390  HValue* result;
8391 
8392  {
8393  NoObservableSideEffectsScope scope(this);
8394 
8395  HValue* length = Add<HLoadNamedField>(
8396  receiver, static_cast<HValue*>(NULL),
8397  HObjectAccess::ForArrayLength(kind));
8398 
8399  IfBuilder if_lengthiszero(this);
8400  HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
8401  length, graph()->GetConstant0(), Token::EQ);
8402  if_lengthiszero.Then();
8403  {
8404  if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8405  }
8406  if_lengthiszero.Else();
8407  {
8408  HValue* elements = AddLoadElements(receiver);
8409 
8410  // Check if we can use the fast inlined Array.shift().
8411  IfBuilder if_inline(this);
8412  if_inline.If<HCompareNumericAndBranch>(
8413  length, inline_threshold, Token::LTE);
8414  if (IsFastSmiOrObjectElementsKind(kind)) {
8415  // We cannot handle copy-on-write backing stores here.
8416  if_inline.AndIf<HCompareMap>(
8417  elements, isolate()->factory()->fixed_array_map());
8418  }
8419  if_inline.Then();
8420  {
8421  // Remember the result.
8422  if (!ast_context()->IsEffect()) {
8423  Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
8424  lengthiszero, kind, LOAD));
8425  }
8426 
8427  // Compute the new length.
8428  HValue* new_length = AddUncasted<HSub>(
8429  length, graph()->GetConstant1());
8430  new_length->ClearFlag(HValue::kCanOverflow);
8431 
8432  // Copy the remaining elements.
8433  LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
8434  {
8435  HValue* new_key = loop.BeginBody(
8436  graph()->GetConstant0(), new_length, Token::LT);
8437  HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
8438  key->ClearFlag(HValue::kCanOverflow);
8439  HValue* element = AddUncasted<HLoadKeyed>(
8440  elements, key, lengthiszero, kind, ALLOW_RETURN_HOLE);
8441  HStoreKeyed* store = Add<HStoreKeyed>(
8442  elements, new_key, element, kind);
8443  store->SetFlag(HValue::kAllowUndefinedAsNaN);
8444  }
8445  loop.EndBody();
8446 
8447  // Put a hole at the end.
8448  HValue* hole = IsFastSmiOrObjectElementsKind(kind)
8449  ? Add<HConstant>(isolate()->factory()->the_hole_value())
8450  : Add<HConstant>(FixedDoubleArray::hole_nan_as_double());
8452  Add<HStoreKeyed>(
8453  elements, new_length, hole, kind, INITIALIZING_STORE);
8454 
8455  // Remember new length.
8456  Add<HStoreNamedField>(
8457  receiver, HObjectAccess::ForArrayLength(kind),
8458  new_length, STORE_TO_INITIALIZED_ENTRY);
8459  }
8460  if_inline.Else();
8461  {
8462  Add<HPushArguments>(receiver);
8463  result = Add<HCallJSFunction>(function, 1, true);
8464  if (!ast_context()->IsEffect()) Push(result);
8465  }
8466  if_inline.End();
8467  }
8468  if_lengthiszero.End();
8469  }
8470  result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8471  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8472  if (!ast_context()->IsEffect()) Drop(1);
8473  ast_context()->ReturnValue(result);
8474  return true;
8475  }
8476  case kArrayIndexOf:
8477  case kArrayLastIndexOf: {
8478  if (receiver_map.is_null()) return false;
8479  if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8480  ElementsKind kind = receiver_map->elements_kind();
8481  if (!IsFastElementsKind(kind)) return false;
8482  if (receiver_map->is_observed()) return false;
8483  if (argument_count != 2) return false;
8484  if (!receiver_map->is_extensible()) return false;
8485 
8486  // If there may be elements accessors in the prototype chain, the fast
8487  // inlined version can't be used.
8488  if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8489 
8490  // If there currently can be no elements accessors on the prototype chain,
8491  // it doesn't mean that there won't be any later. Install a full prototype
8492  // chain check to trap element accessors being installed on the prototype
8493  // chain, which would cause elements to go to dictionary mode and result
8494  // in a map change.
8496  handle(JSObject::cast(receiver_map->prototype()), isolate()),
8498 
8499  HValue* search_element = Pop();
8500  HValue* receiver = Pop();
8501  Drop(1); // Drop function.
8502 
8503  ArrayIndexOfMode mode = (id == kArrayIndexOf)
8505  HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8506 
8507  if (!ast_context()->IsEffect()) Push(index);
8508  Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8509  if (!ast_context()->IsEffect()) Drop(1);
8510  ast_context()->ReturnValue(index);
8511  return true;
8512  }
8513  default:
8514  // Not yet supported for inlining.
8515  break;
8516  }
8517  return false;
8518 }
bool IsEffect() const
Definition: hydrogen.h:763
static double hole_nan_as_double()
Definition: objects-inl.h:2205
HInstruction * AddElementAccess(HValue *elements, HValue *checked_key, HValue *val, HValue *dependency, ElementsKind elements_kind, PropertyAccessType access_type, LoadKeyedHoleMode load_mode=NEVER_RETURN_HOLE)
Definition: hydrogen.cc:2671
HValue * BuildCopyElementsOnWrite(HValue *object, HValue *elements, ElementsKind kind, HValue *length)
Definition: hydrogen.cc:1366
HValue * BuildArrayIndexOf(HValue *receiver, HValue *search_element, ElementsKind kind, ArrayIndexOfMode mode)
Definition: hydrogen.cc:8801
bool is_null() const
Definition: handles.h:124
static Handle< T > null()
Definition: handles.h:123
static bool IsReadOnlyLengthDescriptor(Handle< Map > jsarray_map)
Definition: objects.cc:12803
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
@ STORE_AND_GROW_NO_TRANSITION
Definition: objects.h:161

References AddCheckMap(), v8::internal::HGraphBuilder::AddElementAccess(), v8::internal::HGraphBuilder::AddInstruction(), v8::internal::HGraphBuilder::AddLoadElements(), v8::internal::ALLOW_RETURN_HOLE, ast_context(), BuildArrayIndexOf(), v8::internal::HGraphBuilder::BuildCheckPrototypeMaps(), v8::internal::HGraphBuilder::BuildCopyElementsOnWrite(), BuildStringCharCodeAt(), v8::internal::HGraphBuilder::BuildUncheckedMonomorphicElementAccess(), v8::internal::HValue::ClearFlag(), context(), DCHECK, Drop(), v8::internal::EQ, v8::internal::Isolate::factory(), v8::internal::FAST_HOLEY_ELEMENTS, v8::internal::HGraphBuilder::graph(), v8::internal::handle(), v8::internal::HValue::HasObservableSideEffects(), v8::internal::FixedDoubleArray::hole_nan_as_double(), v8::internal::HValue::id(), v8::internal::INITIALIZING_STORE, v8::internal::Handle< T >::is_null(), v8::internal::AstContext::IsEffect(), v8::internal::IsFastElementsKind(), v8::internal::IsFastSmiOrObjectElementsKind(), v8::internal::HGraphBuilder::isolate(), v8::internal::JSArray::IsReadOnlyLengthDescriptor(), v8::internal::JS_ARRAY_TYPE, v8::internal::HValue::kAllowUndefinedAsNaN, v8::internal::HValue::kCanOverflow, kFirstIndexOf, kLastIndexOf, v8::internal::kMathPowHalf, v8::internal::LOAD, mode(), v8::internal::NEVER_RETURN_HOLE, NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::REMOVABLE_SIMULATE, v8::internal::AstContext::ReturnInstruction(), v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::scope(), v8::internal::STORE, v8::internal::STORE_AND_GROW_NO_TRANSITION, v8::internal::STORE_TO_INITIALIZED_ENTRY, Top(), and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ TryInlineCall()

bool v8::internal::HOptimizedGraphBuilder::TryInlineCall ( Call *  expr)
private

Definition at line 8032 of file hydrogen.cc.

8032  {
8033  return TryInline(expr->target(),
8034  expr->arguments()->length(),
8035  NULL,
8036  expr->id(),
8037  expr->ReturnId(),
8038  NORMAL_RETURN,
8039  ScriptPositionToSourcePosition(expr->position()));
8040 }

References v8::internal::NORMAL_RETURN, NULL, v8::internal::HGraphBuilder::ScriptPositionToSourcePosition(), and TryInline().

Referenced by HandlePolymorphicCallNamed().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineConstruct()

bool v8::internal::HOptimizedGraphBuilder::TryInlineConstruct ( CallNew *  expr,
HValue implicit_return_value 
)
private

Definition at line 8043 of file hydrogen.cc.

8044  {
8045  return TryInline(expr->target(),
8046  expr->arguments()->length(),
8047  implicit_return_value,
8048  expr->id(),
8049  expr->ReturnId(),
8051  ScriptPositionToSourcePosition(expr->position()));
8052 }

References v8::internal::CONSTRUCT_CALL_RETURN, v8::internal::HValue::id(), v8::internal::HGraphBuilder::ScriptPositionToSourcePosition(), and TryInline().

+ Here is the call graph for this function:

◆ TryInlineGetter()

bool v8::internal::HOptimizedGraphBuilder::TryInlineGetter ( Handle< JSFunction getter,
Handle< Map receiver_map,
BailoutId  ast_id,
BailoutId  return_id 
)
private

Definition at line 8055 of file hydrogen.cc.

8058  {
8059  if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
8060  return TryInline(getter,
8061  0,
8062  NULL,
8063  ast_id,
8064  return_id,
8066  source_position());
8067 }
HSourcePosition source_position()
Definition: hydrogen.h:1903
bool TryInlineApiGetter(Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
Definition: hydrogen.cc:8550

References v8::internal::GETTER_CALL_RETURN, NULL, v8::internal::HGraphBuilder::source_position(), TryInline(), and TryInlineApiGetter().

Referenced by BuildMonomorphicAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TryInlineSetter()

bool v8::internal::HOptimizedGraphBuilder::TryInlineSetter ( Handle< JSFunction setter,
Handle< Map receiver_map,
BailoutId  id,
BailoutId  assignment_id,
HValue implicit_return_value 
)
private

Definition at line 8070 of file hydrogen.cc.

8074  {
8075  if (TryInlineApiSetter(setter, receiver_map, id)) return true;
8076  return TryInline(setter,
8077  1,
8078  implicit_return_value,
8079  id, assignment_id,
8081  source_position());
8082 }
bool TryInlineApiSetter(Handle< JSFunction > function, Handle< Map > receiver_map, BailoutId ast_id)
Definition: hydrogen.cc:8564

References v8::internal::SETTER_CALL_RETURN, v8::internal::HGraphBuilder::source_position(), TryInline(), and TryInlineApiSetter().

Referenced by BuildMonomorphicAccess().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ VisitArithmeticExpression()

void v8::internal::HOptimizedGraphBuilder::VisitArithmeticExpression ( BinaryOperation *  expr)
protected

Definition at line 10620 of file hydrogen.cc.

10620  {
10621  CHECK_ALIVE(VisitForValue(expr->left()));
10622  CHECK_ALIVE(VisitForValue(expr->right()));
10623  SetSourcePosition(expr->position());
10624  HValue* right = Pop();
10625  HValue* left = Pop();
10626  HValue* result =
10627  BuildBinaryOperation(expr, left, right,
10628  ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
10630  if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
10631  HBinaryOperation::cast(result)->SetOperandPositions(
10632  zone(),
10633  ScriptPositionToSourcePosition(expr->left()->position()),
10634  ScriptPositionToSourcePosition(expr->right()->position()));
10635  }
10636  return ast_context()->ReturnValue(result);
10637 }
static HValue * cast(HValue *value)

References ast_context(), BuildBinaryOperation(), v8::internal::HValue::cast(), CHECK_ALIVE, NO_PUSH_BEFORE_SIMULATE, v8::internal::HGraphBuilder::Pop(), PUSH_BEFORE_SIMULATE, v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::ScriptPositionToSourcePosition(), v8::internal::HGraphBuilder::SetSourcePosition(), VisitForValue(), and v8::internal::HGraphBuilder::zone().

+ Here is the call graph for this function:

◆ VisitComma()

void v8::internal::HOptimizedGraphBuilder::VisitComma ( BinaryOperation *  expr)
protected

Definition at line 10509 of file hydrogen.cc.

10509  {
10510  CHECK_ALIVE(VisitForEffect(expr->left()));
10511  // Visit the right subexpression in the same AST context as the entire
10512  // expression.
10513  Visit(expr->right());
10514 }
void VisitForEffect(Expression *expr)
Definition: hydrogen.cc:4218

References CHECK_ALIVE, and VisitForEffect().

+ Here is the call graph for this function:

◆ VisitDeclarations()

void v8::internal::HOptimizedGraphBuilder::VisitDeclarations ( ZoneList< Declaration * > *  declarations)

Definition at line 11224 of file hydrogen.cc.

11225  {
11226  DCHECK(globals_.is_empty());
11227  AstVisitor::VisitDeclarations(declarations);
11228  if (!globals_.is_empty()) {
11229  Handle<FixedArray> array =
11230  isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
11231  for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
11232  int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
11235  Add<HDeclareGlobals>(array, flags);
11236  globals_.Rewind(0);
11237  }
11238 }
static U encode(T value)
Definition: utils.h:217

References current_info(), DCHECK, v8::internal::BitFieldBase< T, shift, size, U >::encode(), v8::internal::Isolate::factory(), v8::internal::anonymous_namespace{flags.cc}::flags, globals_, v8::internal::HGraphBuilder::isolate(), and v8::internal::TENURED.

Referenced by BuildGraph(), and TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ VisitDelete()

void v8::internal::HOptimizedGraphBuilder::VisitDelete ( UnaryOperation *  expr)
protected

Definition at line 9828 of file hydrogen.cc.

9828  {
9829  Property* prop = expr->expression()->AsProperty();
9830  VariableProxy* proxy = expr->expression()->AsVariableProxy();
9831  if (prop != NULL) {
9832  CHECK_ALIVE(VisitForValue(prop->obj()));
9833  CHECK_ALIVE(VisitForValue(prop->key()));
9834  HValue* key = Pop();
9835  HValue* obj = Pop();
9836  HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
9837  Add<HPushArguments>(obj, key, Add<HConstant>(function_strict_mode()));
9838  // TODO(olivf) InvokeFunction produces a check for the parameter count,
9839  // even though we are certain to pass the correct number of arguments here.
9840  HInstruction* instr = New<HInvokeFunction>(function, 3);
9841  return ast_context()->ReturnInstruction(instr, expr->id());
9842  } else if (proxy != NULL) {
9843  Variable* var = proxy->var();
9844  if (var->IsUnallocated()) {
9845  Bailout(kDeleteWithGlobalVariable);
9846  } else if (var->IsStackAllocated() || var->IsContextSlot()) {
9847  // Result of deleting non-global variables is false. 'this' is not
9848  // really a variable, though we implement it as one. The
9849  // subexpression does not have side effects.
9850  HValue* value = var->is_this()
9851  ? graph()->GetConstantTrue()
9852  : graph()->GetConstantFalse();
9853  return ast_context()->ReturnValue(value);
9854  } else {
9855  Bailout(kDeleteWithNonGlobalVariable);
9856  }
9857  } else {
9858  // Result of deleting non-property, non-variable reference is true.
9859  // Evaluate the subexpression for side effects.
9860  CHECK_ALIVE(VisitForEffect(expr->expression()));
9861  return ast_context()->ReturnValue(graph()->GetConstantTrue());
9862  }
9863 }
HValue * AddLoadJSBuiltin(Builtins::JavaScript builtin)
Definition: hydrogen.cc:3306

References v8::internal::HGraphBuilder::AddLoadJSBuiltin(), ast_context(), Bailout(), CHECK_ALIVE, function_strict_mode(), v8::internal::HGraphBuilder::graph(), v8::internal::HValue::id(), v8::internal::Variable::is_this(), v8::internal::Variable::IsContextSlot(), v8::internal::Variable::IsStackAllocated(), v8::internal::Variable::IsUnallocated(), NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnInstruction(), v8::internal::AstContext::ReturnValue(), VisitForEffect(), and VisitForValue().

+ Here is the call graph for this function:

◆ VisitExpressions()

void v8::internal::HOptimizedGraphBuilder::VisitExpressions ( ZoneList< Expression * > *  exprs)
protected

Definition at line 4246 of file hydrogen.cc.

4247  {
4248  for (int i = 0; i < exprs->length(); ++i) {
4249  CHECK_ALIVE(VisitForValue(exprs->at(i)));
4250  }
4251 }

References v8::internal::List< T, AllocationPolicy >::at(), CHECK_ALIVE, and VisitForValue().

Referenced by HandlePolymorphicCallNamed().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ VisitForControl()

void v8::internal::HOptimizedGraphBuilder::VisitForControl ( Expression expr,
HBasicBlock *  true_block,
HBasicBlock *  false_block 
)
protected

Definition at line 4238 of file hydrogen.cc.

4240  {
4241  TestContext for_test(this, expr, true_block, false_block);
4242  Visit(expr);
4243 }

Referenced by VisitLogicalExpression(), and VisitNot().

+ Here is the caller graph for this function:

◆ VisitForEffect()

void v8::internal::HOptimizedGraphBuilder::VisitForEffect ( Expression expr)
protected

Definition at line 4218 of file hydrogen.cc.

4218  {
4219  EffectContext for_effect(this);
4220  Visit(expr);
4221 }

Referenced by VisitComma(), VisitDelete(), VisitLogicalExpression(), VisitNot(), and VisitVoid().

+ Here is the caller graph for this function:

◆ VisitForTypeOf()

void v8::internal::HOptimizedGraphBuilder::VisitForTypeOf ( Expression expr)
protected

Definition at line 4231 of file hydrogen.cc.

4231  {
4232  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
4233  for_value.set_for_typeof(true);
4234  Visit(expr);
4235 }

References v8::internal::ARGUMENTS_NOT_ALLOWED.

Referenced by HandleLiteralCompareTypeof(), and VisitTypeof().

+ Here is the caller graph for this function:

◆ VisitForValue()

void v8::internal::HOptimizedGraphBuilder::VisitForValue ( Expression expr,
ArgumentsAllowedFlag  flag = ARGUMENTS_NOT_ALLOWED 
)
protected

Definition at line 4224 of file hydrogen.cc.

4225  {
4226  ValueContext for_value(this, flag);
4227  Visit(expr);
4228 }
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418

References v8::internal::flag.

Referenced by HandleCompoundAssignment(), HandleLiteralCompareNil(), HandlePropertyAssignment(), TryArgumentsAccess(), TryCallApply(), VisitArithmeticExpression(), VisitDelete(), VisitExpressions(), and VisitLogicalExpression().

+ Here is the caller graph for this function:

◆ VisitLogicalExpression()

void v8::internal::HOptimizedGraphBuilder::VisitLogicalExpression ( BinaryOperation *  expr)
protected

Definition at line 10517 of file hydrogen.cc.

10517  {
10518  bool is_logical_and = expr->op() == Token::AND;
10519  if (ast_context()->IsTest()) {
10520  TestContext* context = TestContext::cast(ast_context());
10521  // Translate left subexpression.
10522  HBasicBlock* eval_right = graph()->CreateBasicBlock();
10523  if (is_logical_and) {
10524  CHECK_BAILOUT(VisitForControl(expr->left(),
10525  eval_right,
10526  context->if_false()));
10527  } else {
10528  CHECK_BAILOUT(VisitForControl(expr->left(),
10529  context->if_true(),
10530  eval_right));
10531  }
10532 
10533  // Translate right subexpression by visiting it in the same AST
10534  // context as the entire expression.
10535  if (eval_right->HasPredecessor()) {
10536  eval_right->SetJoinId(expr->RightId());
10537  set_current_block(eval_right);
10538  Visit(expr->right());
10539  }
10540 
10541  } else if (ast_context()->IsValue()) {
10542  CHECK_ALIVE(VisitForValue(expr->left()));
10543  DCHECK(current_block() != NULL);
10544  HValue* left_value = Top();
10545 
10546  // Short-circuit left values that always evaluate to the same boolean value.
10547  if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
10548  // l (evals true) && r -> r
10549  // l (evals true) || r -> l
10550  // l (evals false) && r -> l
10551  // l (evals false) || r -> r
10552  if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
10553  Drop(1);
10554  CHECK_ALIVE(VisitForValue(expr->right()));
10555  }
10556  return ast_context()->ReturnValue(Pop());
10557  }
10558 
10559  // We need an extra block to maintain edge-split form.
10560  HBasicBlock* empty_block = graph()->CreateBasicBlock();
10561  HBasicBlock* eval_right = graph()->CreateBasicBlock();
10562  ToBooleanStub::Types expected(expr->left()->to_boolean_types());
10563  HBranch* test = is_logical_and
10564  ? New<HBranch>(left_value, expected, eval_right, empty_block)
10565  : New<HBranch>(left_value, expected, empty_block, eval_right);
10566  FinishCurrentBlock(test);
10567 
10568  set_current_block(eval_right);
10569  Drop(1); // Value of the left subexpression.
10570  CHECK_BAILOUT(VisitForValue(expr->right()));
10571 
10572  HBasicBlock* join_block =
10573  CreateJoin(empty_block, current_block(), expr->id());
10574  set_current_block(join_block);
10575  return ast_context()->ReturnValue(Pop());
10576 
10577  } else {
10578  DCHECK(ast_context()->IsEffect());
10579  // In an effect context, we don't need the value of the left subexpression,
10580  // only its control flow and side effects. We need an extra block to
10581  // maintain edge-split form.
10582  HBasicBlock* empty_block = graph()->CreateBasicBlock();
10583  HBasicBlock* right_block = graph()->CreateBasicBlock();
10584  if (is_logical_and) {
10585  CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
10586  } else {
10587  CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
10588  }
10589 
10590  // TODO(kmillikin): Find a way to fix this. It's ugly that there are
10591  // actually two empty blocks (one here and one inserted by
10592  // TestContext::BuildBranch, and that they both have an HSimulate though the
10593  // second one is not a merge node, and that we really have no good AST ID to
10594  // put on that first HSimulate.
10595 
10596  if (empty_block->HasPredecessor()) {
10597  empty_block->SetJoinId(expr->id());
10598  } else {
10599  empty_block = NULL;
10600  }
10601 
10602  if (right_block->HasPredecessor()) {
10603  right_block->SetJoinId(expr->RightId());
10604  set_current_block(right_block);
10605  CHECK_BAILOUT(VisitForEffect(expr->right()));
10606  right_block = current_block();
10607  } else {
10608  right_block = NULL;
10609  }
10610 
10611  HBasicBlock* join_block =
10612  CreateJoin(empty_block, right_block, expr->id());
10613  set_current_block(join_block);
10614  // We did not materialize any value in the predecessor environments,
10615  // so there is no need to handle it here.
10616  }
10617 }
void VisitForControl(Expression *expr, HBasicBlock *true_block, HBasicBlock *false_block)
Definition: hydrogen.cc:4238
HBasicBlock * CreateJoin(HBasicBlock *first, HBasicBlock *second, BailoutId join_id)
Definition: hydrogen.cc:3341
#define CHECK_BAILOUT(call)
Definition: hydrogen.cc:4191

References v8::internal::AND, ast_context(), CHECK_ALIVE, CHECK_BAILOUT, context(), CreateJoin(), v8::internal::HGraphBuilder::current_block(), DCHECK, Drop(), v8::internal::HGraphBuilder::FinishCurrentBlock(), v8::internal::HGraphBuilder::graph(), NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::set_current_block(), Top(), VisitForControl(), VisitForEffect(), and VisitForValue().

+ Here is the call graph for this function:

◆ VisitLoopBody()

void v8::internal::HOptimizedGraphBuilder::VisitLoopBody ( IterationStatement stmt,
HBasicBlock *  loop_entry 
)
protected

Definition at line 4936 of file hydrogen.cc.

4937  {
4938  Add<HSimulate>(stmt->StackCheckId());
4939  HStackCheck* stack_check =
4940  HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
4941  DCHECK(loop_entry->IsLoopHeader());
4942  loop_entry->loop_information()->set_stack_check(stack_check);
4943  CHECK_BAILOUT(Visit(stmt->body()));
4944 }

References v8::internal::IterationStatement::body(), CHECK_BAILOUT, DCHECK, and v8::internal::IterationStatement::StackCheckId().

+ Here is the call graph for this function:

◆ VisitNot()

void v8::internal::HOptimizedGraphBuilder::VisitNot ( UnaryOperation *  expr)
protected

Definition at line 9880 of file hydrogen.cc.

9880  {
9881  if (ast_context()->IsTest()) {
9882  TestContext* context = TestContext::cast(ast_context());
9883  VisitForControl(expr->expression(),
9884  context->if_false(),
9885  context->if_true());
9886  return;
9887  }
9888 
9889  if (ast_context()->IsEffect()) {
9890  VisitForEffect(expr->expression());
9891  return;
9892  }
9893 
9894  DCHECK(ast_context()->IsValue());
9895  HBasicBlock* materialize_false = graph()->CreateBasicBlock();
9896  HBasicBlock* materialize_true = graph()->CreateBasicBlock();
9897  CHECK_BAILOUT(VisitForControl(expr->expression(),
9898  materialize_false,
9899  materialize_true));
9900 
9901  if (materialize_false->HasPredecessor()) {
9902  materialize_false->SetJoinId(expr->MaterializeFalseId());
9903  set_current_block(materialize_false);
9904  Push(graph()->GetConstantFalse());
9905  } else {
9906  materialize_false = NULL;
9907  }
9908 
9909  if (materialize_true->HasPredecessor()) {
9910  materialize_true->SetJoinId(expr->MaterializeTrueId());
9911  set_current_block(materialize_true);
9912  Push(graph()->GetConstantTrue());
9913  } else {
9914  materialize_true = NULL;
9915  }
9916 
9917  HBasicBlock* join =
9918  CreateJoin(materialize_false, materialize_true, expr->id());
9919  set_current_block(join);
9920  if (join != NULL) return ast_context()->ReturnValue(Pop());
9921 }

References ast_context(), CHECK_BAILOUT, context(), CreateJoin(), DCHECK, v8::internal::HGraphBuilder::graph(), NULL, v8::internal::HGraphBuilder::Pop(), v8::internal::HGraphBuilder::Push(), v8::internal::AstContext::ReturnValue(), v8::internal::HGraphBuilder::set_current_block(), VisitForControl(), and VisitForEffect().

+ Here is the call graph for this function:

◆ VisitStatements()

void v8::internal::HOptimizedGraphBuilder::VisitStatements ( ZoneList< Statement * > *  statements)
protectedvirtual

Definition at line 4518 of file hydrogen.cc.

4518  {
4519  for (int i = 0; i < statements->length(); i++) {
4520  Statement* stmt = statements->at(i);
4521  CHECK_ALIVE(Visit(stmt));
4522  if (stmt->IsJump()) break;
4523  }
4524 }

References v8::internal::List< T, AllocationPolicy >::at(), CHECK_ALIVE, and v8::internal::Statement::IsJump().

Referenced by BuildGraph(), and TryInline().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ VisitTypeof()

void v8::internal::HOptimizedGraphBuilder::VisitTypeof ( UnaryOperation *  expr)
protected

Definition at line 9872 of file hydrogen.cc.

9872  {
9873  CHECK_ALIVE(VisitForTypeOf(expr->expression()));
9874  HValue* value = Pop();
9875  HInstruction* instr = New<HTypeof>(value);
9876  return ast_context()->ReturnInstruction(instr, expr->id());
9877 }

References ast_context(), CHECK_ALIVE, v8::internal::HValue::id(), v8::internal::HGraphBuilder::Pop(), v8::internal::AstContext::ReturnInstruction(), and VisitForTypeOf().

+ Here is the call graph for this function:

◆ VisitVoid()

void v8::internal::HOptimizedGraphBuilder::VisitVoid ( UnaryOperation *  expr)
protected

Definition at line 9866 of file hydrogen.cc.

9866  {
9867  CHECK_ALIVE(VisitForEffect(expr->expression()));
9868  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9869 }

References ast_context(), CHECK_ALIVE, v8::internal::HGraphBuilder::graph(), v8::internal::AstContext::ReturnValue(), and VisitForEffect().

+ Here is the call graph for this function:

Friends And Related Function Documentation

◆ AstContext

friend class AstContext
friend

Definition at line 2737 of file hydrogen.h.

◆ FunctionState

friend class FunctionState
friend

Definition at line 2736 of file hydrogen.h.

Referenced by TryInline().

◆ HOsrBuilder

friend class HOsrBuilder
friend

Definition at line 2739 of file hydrogen.h.

◆ KeyedLoadFastElementStub

friend class KeyedLoadFastElementStub
friend

Definition at line 2738 of file hydrogen.h.

Member Data Documentation

◆ ast_context_

AstContext* v8::internal::HOptimizedGraphBuilder::ast_context_
private

Definition at line 2724 of file hydrogen.h.

Referenced by ast_context(), and set_ast_context().

◆ break_scope_

BreakAndContinueScope* v8::internal::HOptimizedGraphBuilder::break_scope_
private

Definition at line 2727 of file hydrogen.h.

Referenced by break_scope(), and set_break_scope().

◆ function_state_

FunctionState* v8::internal::HOptimizedGraphBuilder::function_state_
private

Definition at line 2717 of file hydrogen.h.

Referenced by function_state(), HOptimizedGraphBuilder(), and set_function_state().

◆ globals_

ZoneList<Handle<Object> > v8::internal::HOptimizedGraphBuilder::globals_
private

Definition at line 2730 of file hydrogen.h.

Referenced by VisitDeclarations().

◆ initial_function_state_

FunctionState v8::internal::HOptimizedGraphBuilder::initial_function_state_
private

Definition at line 2720 of file hydrogen.h.

Referenced by HOptimizedGraphBuilder().

◆ inline_bailout_

bool v8::internal::HOptimizedGraphBuilder::inline_bailout_
private

Definition at line 2732 of file hydrogen.h.

◆ inlined_count_

int v8::internal::HOptimizedGraphBuilder::inlined_count_
private

Definition at line 2729 of file hydrogen.h.

Referenced by TryInline().

◆ kInlineFunctionGenerators

const HOptimizedGraphBuilder::InlineFunctionGenerator v8::internal::HOptimizedGraphBuilder::kInlineFunctionGenerators
staticprotected
Initial value:
= {
}

Definition at line 2143 of file hydrogen.h.

◆ kMaxCallPolymorphism

const int v8::internal::HOptimizedGraphBuilder::kMaxCallPolymorphism = 4
staticprotected

Definition at line 2145 of file hydrogen.h.

Referenced by HandlePolymorphicCallNamed().

◆ kMaxFastLiteralDepth

const int v8::internal::HOptimizedGraphBuilder::kMaxFastLiteralDepth = 3
staticprotected

Definition at line 2157 of file hydrogen.h.

◆ kMaxFastLiteralProperties

const int v8::internal::HOptimizedGraphBuilder::kMaxFastLiteralProperties = 8
staticprotected

Definition at line 2158 of file hydrogen.h.

◆ kMaxLoadPolymorphism

const int v8::internal::HOptimizedGraphBuilder::kMaxLoadPolymorphism = 4
staticprotected

◆ kMaxStorePolymorphism

const int v8::internal::HOptimizedGraphBuilder::kMaxStorePolymorphism = 4
staticprotected

◆ kUnlimitedMaxInlinedNodes

const int v8::internal::HOptimizedGraphBuilder::kUnlimitedMaxInlinedNodes = 10000
staticprotected

Definition at line 2152 of file hydrogen.h.

Referenced by TryInline().

◆ kUnlimitedMaxInlinedNodesCumulative

const int v8::internal::HOptimizedGraphBuilder::kUnlimitedMaxInlinedNodesCumulative = 10000
staticprotected

Definition at line 2153 of file hydrogen.h.

Referenced by TryInline().

◆ kUnlimitedMaxInlinedSourceSize

const int v8::internal::HOptimizedGraphBuilder::kUnlimitedMaxInlinedSourceSize = 100000
staticprotected

Definition at line 2151 of file hydrogen.h.

Referenced by InliningAstSize().

◆ osr_

HOsrBuilder* v8::internal::HOptimizedGraphBuilder::osr_
private

Definition at line 2734 of file hydrogen.h.

Referenced by osr().


The documentation for this class was generated from the following files: