blob: 3e741db6a38e91504abca280eeca4794f12c1e6b [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_KERNEL_BINARY_FLOWGRAPH_H_
#define RUNTIME_VM_KERNEL_BINARY_FLOWGRAPH_H_
#if !defined(DART_PRECOMPILED_RUNTIME)
#include <map>
#include "vm/kernel.h"
#include "vm/kernel_binary.h"
#include "vm/kernel_to_il.h"
#include "vm/object.h"
namespace dart {
namespace kernel {
class StreamingDartTypeTranslator {
public:
StreamingDartTypeTranslator(StreamingFlowGraphBuilder* builder,
bool finalize = false);
// Can return a malformed type.
AbstractType& BuildType();
// Will return `TypeArguments::null()` in case any of the arguments are
// malformed.
const TypeArguments& BuildTypeArguments(intptr_t length);
// Will return `TypeArguments::null()` in case any of the arguments are
// malformed.
const TypeArguments& BuildInstantiatedTypeArguments(
const dart::Class& receiver_class,
intptr_t length);
const Type& ReceiverType(const dart::Class& klass);
private:
// Can build a malformed type.
void BuildTypeInternal();
void BuildInterfaceType(bool simple);
void BuildFunctionType(bool simple);
void BuildTypeParameterType();
class TypeParameterScope {
public:
TypeParameterScope(StreamingDartTypeTranslator* translator,
intptr_t* parameters,
intptr_t parameters_count)
: parameters_(parameters),
parameters_count_(parameters_count),
outer_(translator->type_parameter_scope_),
translator_(translator) {
translator_->type_parameter_scope_ = this;
}
~TypeParameterScope() {
delete[] parameters_;
translator_->type_parameter_scope_ = outer_;
}
TypeParameterScope* outer() const { return outer_; }
intptr_t* parameters() const { return parameters_; }
intptr_t parameters_count() const { return parameters_count_; }
private:
intptr_t* parameters_;
intptr_t parameters_count_;
TypeParameterScope* outer_;
StreamingDartTypeTranslator* translator_;
};
StreamingFlowGraphBuilder* builder_;
TranslationHelper& translation_helper_;
ActiveClass* active_class_;
TypeParameterScope* type_parameter_scope_;
Zone* zone_;
AbstractType& result_;
bool finalize_;
};
class StreamingConstantEvaluator {
public:
explicit StreamingConstantEvaluator(StreamingFlowGraphBuilder* builder);
virtual ~StreamingConstantEvaluator() {}
Instance& EvaluateExpression(intptr_t offset, bool reset_position = true);
Instance& EvaluateListLiteral(intptr_t offset, bool reset_position = true);
Instance& EvaluateMapLiteral(intptr_t offset, bool reset_position = true);
Instance& EvaluateConstructorInvocation(intptr_t offset,
bool reset_position = true);
Object& EvaluateExpressionSafe(intptr_t offset);
private:
void EvaluateVariableGet();
void EvaluateVariableGet(uint8_t payload);
void EvaluatePropertyGet();
void EvaluateStaticGet();
void EvaluateMethodInvocation();
void EvaluateStaticInvocation();
void EvaluateConstructorInvocationInternal();
void EvaluateNot();
void EvaluateLogicalExpression();
void EvaluateConditionalExpression();
void EvaluateStringConcatenation();
void EvaluateSymbolLiteral();
void EvaluateTypeLiteral();
void EvaluateListLiteralInternal();
void EvaluateMapLiteralInternal();
void EvaluateLet();
void EvaluateBigIntLiteral();
void EvaluateStringLiteral();
void EvaluateIntLiteral(uint8_t payload);
void EvaluateIntLiteral(bool is_negative);
void EvaluateDoubleLiteral();
void EvaluateBoolLiteral(bool value);
void EvaluateNullLiteral();
const Object& RunFunction(const Function& function,
intptr_t argument_count,
const Instance* receiver,
const TypeArguments* type_args);
const Object& RunFunction(const Function& function,
const Array& arguments,
const Array& names);
RawObject* EvaluateConstConstructorCall(const dart::Class& type_class,
const TypeArguments& type_arguments,
const Function& constructor,
const Object& argument);
const TypeArguments* TranslateTypeArguments(const Function& target,
dart::Class* target_klass);
void AssertBoolInCheckedMode() {
if (isolate_->type_checks() && !result_.IsBool()) {
translation_helper_.ReportError("Expected boolean expression.");
}
}
bool EvaluateBooleanExpressionHere();
bool GetCachedConstant(intptr_t kernel_offset, Instance* value);
void CacheConstantValue(intptr_t kernel_offset, const Instance& value);
StreamingFlowGraphBuilder* builder_;
Isolate* isolate_;
Zone* zone_;
TranslationHelper& translation_helper_;
StreamingDartTypeTranslator& type_translator_;
Script& script_;
Instance& result_;
};
class StreamingFlowGraphBuilder {
public:
StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
const uint8_t* buffer,
intptr_t buffer_length)
: flow_graph_builder_(flow_graph_builder),
translation_helper_(flow_graph_builder->translation_helper_),
zone_(flow_graph_builder->zone_),
reader_(new Reader(buffer, buffer_length)),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true) {}
Fragment BuildExpressionAt(intptr_t kernel_offset);
Fragment BuildStatementAt(intptr_t kernel_offset);
private:
Fragment BuildExpression(TokenPosition* position = NULL);
Fragment BuildStatement();
intptr_t ReaderOffset();
void SetOffset(intptr_t offset);
void SkipBytes(intptr_t skip);
bool ReadBool();
uint8_t ReadByte();
uint32_t ReadUInt();
uint32_t PeekUInt();
intptr_t ReadListLength();
StringIndex ReadStringReference();
NameIndex ReadCanonicalNameReference();
StringIndex ReadNameAsStringIndex();
const dart::String& ReadNameAsMethodName();
const dart::String& ReadNameAsGetterName();
const dart::String& ReadNameAsSetterName();
void SkipStringReference();
void SkipCanonicalNameReference();
void SkipDartType();
void SkipOptionalDartType();
void SkipInterfaceType(bool simple);
void SkipFunctionType(bool simple);
void SkipExpression();
void SkipStatement();
void SkipName();
void SkipArguments();
void SkipVariableDeclaration();
TokenPosition ReadPosition(bool record = true);
Tag ReadTag(uint8_t* payload = NULL);
Tag PeekTag(uint8_t* payload = NULL);
word ReadFlags();
void loop_depth_inc();
void loop_depth_dec();
intptr_t for_in_depth();
void for_in_depth_inc();
void for_in_depth_dec();
void catch_depth_inc();
void catch_depth_dec();
void try_depth_inc();
void try_depth_dec();
intptr_t CurrentTryIndex();
intptr_t AllocateTryIndex();
LocalVariable* CurrentException();
LocalVariable* CurrentStackTrace();
CatchBlock* catch_block();
ActiveClass* active_class();
ScopeBuildingResult* scopes();
ParsedFunction* parsed_function();
TryFinallyBlock* try_finally_block();
SwitchBlock* switch_block();
BreakableBlock* breakable_block();
GrowableArray<YieldContinuation>& yield_continuations();
Value* stack();
Value* Pop();
Tag PeekArgumentsFirstPositionalTag();
const TypeArguments& PeekArgumentsInstantiatedType(const dart::Class& klass);
intptr_t PeekArgumentsCount();
intptr_t PeekArgumentsTypeCount();
void SkipArgumentsBeforeActualArguments();
LocalVariable* LookupVariable(intptr_t kernel_offset);
LocalVariable* MakeTemporary();
Token::Kind MethodKind(const dart::String& name);
dart::RawFunction* LookupMethodByMember(NameIndex target,
const dart::String& method_name);
bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
bool NeedsDebugStepCheck(Value* value, TokenPosition position);
void InlineBailout(const char* reason);
Fragment DebugStepCheck(TokenPosition position);
Fragment LoadLocal(LocalVariable* variable);
Fragment Return(TokenPosition position);
Fragment PushArgument();
Fragment EvaluateAssertion();
Fragment RethrowException(TokenPosition position, int catch_try_index);
Fragment ThrowNoSuchMethodError();
Fragment Constant(const Object& value);
Fragment IntConstant(int64_t value);
Fragment LoadStaticField();
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
const Array& argument_names);
Fragment InstanceCall(TokenPosition position,
const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
intptr_t num_args_checked = 1);
Fragment InstanceCall(TokenPosition position,
const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
const Array& argument_names,
intptr_t num_args_checked);
Fragment ThrowException(TokenPosition position);
Fragment BooleanNegate();
Fragment TranslateInstantiatedTypeArguments(
const TypeArguments& type_arguments);
Fragment StrictCompare(Token::Kind kind, bool number_check = false);
Fragment AllocateObject(const dart::Class& klass, intptr_t argument_count);
Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
Fragment StoreStaticField(TokenPosition position, const dart::Field& field);
Fragment StringInterpolate(TokenPosition position);
Fragment StringInterpolateSingle(TokenPosition position);
Fragment ThrowTypeError();
Fragment LoadInstantiatorTypeArguments();
Fragment LoadFunctionTypeArguments();
Fragment InstantiateType(const AbstractType& type);
Fragment CreateArray();
Fragment StoreIndexed(intptr_t class_id);
Fragment CheckStackOverflow();
Fragment CloneContext();
Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally,
intptr_t target_context_depth);
Fragment BranchIfTrue(TargetEntryInstr** then_entry,
TargetEntryInstr** otherwise_entry,
bool negate);
Fragment BranchIfEqual(TargetEntryInstr** then_entry,
TargetEntryInstr** otherwise_entry,
bool negate);
Fragment BranchIfNull(TargetEntryInstr** then_entry,
TargetEntryInstr** otherwise_entry,
bool negate = false);
Fragment CatchBlockEntry(const Array& handler_types,
intptr_t handler_index,
bool needs_stacktrace);
Fragment TryCatch(int try_handler_index);
Fragment Drop();
Fragment NullConstant();
JoinEntryInstr* BuildJoinEntry();
JoinEntryInstr* BuildJoinEntry(intptr_t try_index);
Fragment Goto(JoinEntryInstr* destination);
Fragment BuildImplicitClosureCreation(const Function& target);
Fragment CheckBooleanInCheckedMode();
Fragment CheckAssignableInCheckedMode(const dart::AbstractType& dst_type,
const dart::String& dst_name);
Fragment CheckVariableTypeInCheckedMode(intptr_t variable_kernel_position);
Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type,
const dart::String& name_symbol);
Fragment EnterScope(intptr_t kernel_offset, bool* new_context = NULL);
Fragment ExitScope(intptr_t kernel_offset);
Fragment TranslateCondition(bool* negate);
const TypeArguments& BuildTypeArguments();
Fragment BuildArguments(Array* argument_names,
intptr_t* argument_count,
bool skip_push_arguments = false,
bool do_drop = false);
Fragment BuildArgumentsFromActualArguments(Array* argument_names,
bool skip_push_arguments = false,
bool do_drop = false);
Fragment BuildInvalidExpression(TokenPosition* position);
Fragment BuildVariableGet(TokenPosition* position);
Fragment BuildVariableGet(uint8_t payload, TokenPosition* position);
Fragment BuildVariableSet(TokenPosition* position);
Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
Fragment BuildPropertyGet(TokenPosition* position);
Fragment BuildPropertySet(TokenPosition* position);
Fragment BuildDirectPropertyGet(TokenPosition* position);
Fragment BuildDirectPropertySet(TokenPosition* position);
Fragment BuildStaticGet(TokenPosition* position);
Fragment BuildStaticSet(TokenPosition* position);
Fragment BuildMethodInvocation(TokenPosition* position);
Fragment BuildDirectMethodInvocation(TokenPosition* position);
Fragment BuildStaticInvocation(bool is_const, TokenPosition* position);
Fragment BuildConstructorInvocation(bool is_const, TokenPosition* position);
Fragment BuildNot(TokenPosition* position);
Fragment BuildLogicalExpression(TokenPosition* position);
Fragment BuildConditionalExpression(TokenPosition* position);
Fragment BuildStringConcatenation(TokenPosition* position);
Fragment BuildIsExpression(TokenPosition* position);
Fragment BuildAsExpression(TokenPosition* position);
Fragment BuildSymbolLiteral(TokenPosition* position);
Fragment BuildTypeLiteral(TokenPosition* position);
Fragment BuildThisExpression(TokenPosition* position);
Fragment BuildRethrow(TokenPosition* position);
Fragment BuildThrow(TokenPosition* position);
Fragment BuildListLiteral(bool is_const, TokenPosition* position);
Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
Fragment BuildLet(TokenPosition* position);
Fragment BuildBigIntLiteral(TokenPosition* position);
Fragment BuildStringLiteral(TokenPosition* position);
Fragment BuildIntLiteral(uint8_t payload, TokenPosition* position);
Fragment BuildIntLiteral(bool is_negative, TokenPosition* position);
Fragment BuildDoubleLiteral(TokenPosition* position);
Fragment BuildBoolLiteral(bool value, TokenPosition* position);
Fragment BuildNullLiteral(TokenPosition* position);
Fragment BuildInvalidStatement();
Fragment BuildExpressionStatement();
Fragment BuildBlock();
Fragment BuildEmptyStatement();
Fragment BuildAssertStatement();
Fragment BuildLabeledStatement();
Fragment BuildBreakStatement();
Fragment BuildWhileStatement();
Fragment BuildDoStatement();
Fragment BuildForStatement();
Fragment BuildForInStatement(bool async);
Fragment BuildSwitchStatement();
Fragment BuildContinueSwitchStatement();
Fragment BuildIfStatement();
Fragment BuildReturnStatement();
Fragment BuildTryCatch();
Fragment BuildTryFinally();
Fragment BuildYieldStatement();
Fragment BuildVariableDeclaration(bool has_tag);
FlowGraphBuilder* flow_graph_builder_;
TranslationHelper& translation_helper_;
Zone* zone_;
Reader* reader_;
StreamingConstantEvaluator constant_evaluator_;
StreamingDartTypeTranslator type_translator_;
friend class StreamingConstantEvaluator;
friend class StreamingDartTypeTranslator;
};
} // namespace kernel
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_KERNEL_BINARY_FLOWGRAPH_H_