| Index: runtime/vm/flow_graph_compiler_shared.cc
|
| ===================================================================
|
| --- runtime/vm/flow_graph_compiler_shared.cc (revision 8400)
|
| +++ runtime/vm/flow_graph_compiler_shared.cc (working copy)
|
| @@ -1,330 +0,0 @@
|
| -// Copyright (c) 2012, 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.
|
| -
|
| -#include "vm/flow_graph_compiler_shared.h"
|
| -
|
| -#include "vm/debugger.h"
|
| -#include "vm/intermediate_language.h"
|
| -#include "vm/intrinsifier.h"
|
| -#include "vm/longjump.h"
|
| -#include "vm/parser.h"
|
| -#include "vm/stub_code.h"
|
| -
|
| -namespace dart {
|
| -
|
| -DECLARE_FLAG(bool, enable_type_checks);
|
| -DECLARE_FLAG(bool, intrinsify);
|
| -DECLARE_FLAG(int, optimization_counter_threshold);
|
| -DECLARE_FLAG(bool, trace_functions);
|
| -DECLARE_FLAG(bool, report_usage_count);
|
| -
|
| -FlowGraphCompilerShared::FlowGraphCompilerShared(
|
| - Assembler* assembler,
|
| - const ParsedFunction& parsed_function,
|
| - const GrowableArray<BlockEntryInstr*>& block_order,
|
| - bool is_optimizing)
|
| - : assembler_(assembler),
|
| - parsed_function_(parsed_function),
|
| - block_order_(block_order),
|
| - current_block_(NULL),
|
| - exception_handlers_list_(NULL),
|
| - pc_descriptors_list_(NULL),
|
| - stackmap_builder_(NULL),
|
| - block_info_(block_order.length()),
|
| - deopt_stubs_(),
|
| - is_optimizing_(is_optimizing) {
|
| - ASSERT(assembler != NULL);
|
| -}
|
| -
|
| -
|
| -FlowGraphCompilerShared::~FlowGraphCompilerShared() {
|
| - // BlockInfos are zone-allocated, so their destructors are not called.
|
| - // Verify the labels explicitly here.
|
| - for (int i = 0; i < block_info_.length(); ++i) {
|
| - ASSERT(!block_info_[i]->label.IsLinked());
|
| - ASSERT(!block_info_[i]->label.HasNear());
|
| - }
|
| -}
|
| -
|
| -void FlowGraphCompilerShared::InitCompiler() {
|
| - pc_descriptors_list_ = new DescriptorList();
|
| - exception_handlers_list_ = new ExceptionHandlerList();
|
| - block_info_.Clear();
|
| - for (int i = 0; i < block_order_.length(); ++i) {
|
| - block_info_.Add(new BlockInfo());
|
| - }
|
| -}
|
| -
|
| -
|
| -intptr_t FlowGraphCompilerShared::StackSize() const {
|
| - return parsed_function_.stack_local_count() +
|
| - parsed_function_.copied_parameter_count();
|
| -}
|
| -
|
| -
|
| -Label* FlowGraphCompilerShared::GetBlockLabel(
|
| - BlockEntryInstr* block_entry) const {
|
| - intptr_t block_index = block_entry->postorder_number();
|
| - return &block_info_[block_index]->label;
|
| -}
|
| -
|
| -
|
| -bool FlowGraphCompilerShared::IsNextBlock(TargetEntryInstr* block_entry) const {
|
| - intptr_t current_index = reverse_index(current_block()->postorder_number());
|
| - return block_order_[current_index + 1] == block_entry;
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::AddExceptionHandler(intptr_t try_index,
|
| - intptr_t pc_offset) {
|
| - exception_handlers_list_->AddHandler(try_index, pc_offset);
|
| -}
|
| -
|
| -
|
| -// Uses current pc position and try-index.
|
| -void FlowGraphCompilerShared::AddCurrentDescriptor(PcDescriptors::Kind kind,
|
| - intptr_t cid,
|
| - intptr_t token_index,
|
| - intptr_t try_index) {
|
| - pc_descriptors_list()->AddDescriptor(kind,
|
| - assembler()->CodeSize(),
|
| - cid,
|
| - token_index,
|
| - try_index);
|
| -}
|
| -
|
| -
|
| -Label* FlowGraphCompilerShared::AddDeoptStub(intptr_t deopt_id,
|
| - intptr_t deopt_token_index,
|
| - intptr_t try_index,
|
| - DeoptReasonId reason,
|
| - Register reg1,
|
| - Register reg2) {
|
| - DeoptimizationStub* stub =
|
| - new DeoptimizationStub(deopt_id, deopt_token_index, try_index, reason);
|
| - stub->Push(reg1);
|
| - stub->Push(reg2);
|
| - deopt_stubs_.Add(stub);
|
| - return stub->entry_label();
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::FinalizeExceptionHandlers(const Code& code) {
|
| - ASSERT(exception_handlers_list_ != NULL);
|
| - const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
|
| - exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint()));
|
| - code.set_exception_handlers(handlers);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::FinalizePcDescriptors(const Code& code) {
|
| - ASSERT(pc_descriptors_list_ != NULL);
|
| - const PcDescriptors& descriptors = PcDescriptors::Handle(
|
| - pc_descriptors_list_->FinalizePcDescriptors(code.EntryPoint()));
|
| - descriptors.Verify(parsed_function_.function().is_optimizable());
|
| - code.set_pc_descriptors(descriptors);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::FinalizeStackmaps(const Code& code) {
|
| - if (stackmap_builder_ == NULL) {
|
| - // The unoptimizing compiler has no stack maps.
|
| - code.set_stackmaps(Array::Handle());
|
| - } else {
|
| - // Finalize the stack map array and add it to the code object.
|
| - code.set_stackmaps(
|
| - Array::Handle(stackmap_builder_->FinalizeStackmaps(code)));
|
| - }
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::FinalizeVarDescriptors(const Code& code) {
|
| - const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle(
|
| - parsed_function_.node_sequence()->scope()->GetVarDescriptors());
|
| - code.set_var_descriptors(var_descs);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::FinalizeComments(const Code& code) {
|
| - code.set_comments(assembler()->GetCodeComments());
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateDeferredCode() {
|
| - for (intptr_t i = 0; i < deopt_stubs_.length(); i++) {
|
| - deopt_stubs_[i]->GenerateCode(this);
|
| - }
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateInstanceCall(
|
| - intptr_t cid,
|
| - intptr_t token_index,
|
| - intptr_t try_index,
|
| - const String& function_name,
|
| - intptr_t argument_count,
|
| - const Array& argument_names,
|
| - intptr_t checked_argument_count) {
|
| - ICData& ic_data =
|
| - ICData::ZoneHandle(ICData::New(parsed_function().function(),
|
| - function_name,
|
| - cid,
|
| - checked_argument_count));
|
| - const Array& arguments_descriptor =
|
| - CodeGenerator::ArgumentsDescriptor(argument_count, argument_names);
|
| - uword label_address = 0;
|
| - switch (checked_argument_count) {
|
| - case 1:
|
| - label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
|
| - break;
|
| - case 2:
|
| - label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
|
| - break;
|
| - default:
|
| - UNIMPLEMENTED();
|
| - }
|
| - ExternalLabel target_label("InlineCache", label_address);
|
| -
|
| - const intptr_t descr_offset = EmitInstanceCall(&target_label,
|
| - ic_data,
|
| - arguments_descriptor,
|
| - argument_count);
|
| - pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall,
|
| - descr_offset,
|
| - cid,
|
| - token_index,
|
| - try_index);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateStaticCall(intptr_t cid,
|
| - intptr_t token_index,
|
| - intptr_t try_index,
|
| - const Function& function,
|
| - intptr_t argument_count,
|
| - const Array& argument_names) {
|
| - const Array& arguments_descriptor =
|
| - CodeGenerator::ArgumentsDescriptor(argument_count, argument_names);
|
| - const intptr_t descr_offset = EmitStaticCall(function,
|
| - arguments_descriptor,
|
| - argument_count);
|
| - pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall,
|
| - descr_offset,
|
| - cid,
|
| - token_index,
|
| - try_index);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::Bailout(const char* reason) {
|
| - const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
|
| - const char* function_name = parsed_function().function().ToCString();
|
| - intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
|
| - char* chars = reinterpret_cast<char*>(
|
| - Isolate::Current()->current_zone()->Allocate(len));
|
| - OS::SNPrint(chars, len, kFormat, function_name, reason);
|
| - const Error& error = Error::Handle(
|
| - LanguageError::New(String::Handle(String::New(chars))));
|
| - Isolate::Current()->long_jump_base()->Jump(1, error);
|
| -}
|
| -
|
| -
|
| -static bool CanOptimize() {
|
| - return !FLAG_report_usage_count &&
|
| - (FLAG_optimization_counter_threshold >= 0) &&
|
| - !Isolate::Current()->debugger()->IsActive();
|
| -}
|
| -
|
| -
|
| -// Returns 'true' if code generation for this function is complete, i.e.,
|
| -// no fall-through to regular code is needed.
|
| -bool FlowGraphCompilerShared::TryIntrinsify() {
|
| - if (!CanOptimize()) return false;
|
| - // Intrinsification skips arguments checks, therefore disable if in checked
|
| - // mode.
|
| - if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) {
|
| - if ((parsed_function().function().kind() == RawFunction::kImplicitGetter)) {
|
| - // An implicit getter must have a specific AST structure.
|
| - const SequenceNode& sequence_node = *parsed_function().node_sequence();
|
| - ASSERT(sequence_node.length() == 1);
|
| - ASSERT(sequence_node.NodeAt(0)->IsReturnNode());
|
| - const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode();
|
| - ASSERT(return_node.value()->IsLoadInstanceFieldNode());
|
| - const LoadInstanceFieldNode& load_node =
|
| - *return_node.value()->AsLoadInstanceFieldNode();
|
| - GenerateInlinedGetter(load_node.field().Offset());
|
| - return true;
|
| - }
|
| - if ((parsed_function().function().kind() == RawFunction::kImplicitSetter)) {
|
| - // An implicit setter must have a specific AST structure.
|
| - // Sequence node has one store node and one return NULL node.
|
| - const SequenceNode& sequence_node = *parsed_function().node_sequence();
|
| - ASSERT(sequence_node.length() == 2);
|
| - ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode());
|
| - ASSERT(sequence_node.NodeAt(1)->IsReturnNode());
|
| - const StoreInstanceFieldNode& store_node =
|
| - *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
|
| - GenerateInlinedSetter(store_node.field().Offset());
|
| - return true;
|
| - }
|
| - }
|
| - // Even if an intrinsified version of the function was successfully
|
| - // generated, it may fall through to the non-intrinsified method body.
|
| - if (!FLAG_trace_functions) {
|
| - return Intrinsifier::Intrinsify(parsed_function().function(), assembler());
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateNumberTypeCheck(
|
| - Register kClassIdReg,
|
| - const AbstractType& type,
|
| - Label* is_instance_lbl,
|
| - Label* is_not_instance_lbl) {
|
| - GrowableArray<intptr_t> args;
|
| - if (type.IsNumberInterface()) {
|
| - args.Add(kDouble);
|
| - args.Add(kMint);
|
| - args.Add(kBigint);
|
| - } else if (type.IsIntInterface()) {
|
| - args.Add(kMint);
|
| - args.Add(kBigint);
|
| - } else if (type.IsDoubleInterface()) {
|
| - args.Add(kDouble);
|
| - }
|
| - CheckClassIds(kClassIdReg, args, is_instance_lbl, is_not_instance_lbl);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateStringTypeCheck(
|
| - Register kClassIdReg,
|
| - Label* is_instance_lbl,
|
| - Label* is_not_instance_lbl) {
|
| - GrowableArray<intptr_t> args;
|
| - args.Add(kOneByteString);
|
| - args.Add(kTwoByteString);
|
| - args.Add(kFourByteString);
|
| - args.Add(kExternalOneByteString);
|
| - args.Add(kExternalTwoByteString);
|
| - args.Add(kExternalFourByteString);
|
| - CheckClassIds(kClassIdReg, args, is_instance_lbl, is_not_instance_lbl);
|
| -}
|
| -
|
| -
|
| -void FlowGraphCompilerShared::GenerateListTypeCheck(
|
| - Register kClassIdReg,
|
| - Label* is_instance_lbl) {
|
| - Label unknown;
|
| - GrowableArray<intptr_t> args;
|
| - args.Add(kArray);
|
| - args.Add(kGrowableObjectArray);
|
| - args.Add(kImmutableArray);
|
| - CheckClassIds(kClassIdReg, args, is_instance_lbl, &unknown);
|
| - assembler()->Bind(&unknown);
|
| -}
|
| -
|
| -} // namespace dart
|
| -
|
| -
|
|
|