Chromium Code Reviews| Index: runtime/vm/kernel_binary_flowgraph.cc |
| diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc |
| index f65488af1f70c6ffd51ae79d14dfed33d0f5beee..ad458ae036ec2159a28ce1f7fc523415ee70e999 100644 |
| --- a/runtime/vm/kernel_binary_flowgraph.cc |
| +++ b/runtime/vm/kernel_binary_flowgraph.cc |
| @@ -9,14 +9,111 @@ |
| namespace dart { |
| namespace kernel { |
| -#define Z (flow_graph_builder_->zone_) |
| -#define H (flow_graph_builder_->translation_helper_) |
| +#define Z (zone_) |
| +#define H (translation_helper_) |
| + |
| +StreamingConstantEvaluator::StreamingConstantEvaluator( |
| + StreamingFlowGraphBuilder* builder, |
| + Zone* zone, |
| + TranslationHelper* h, |
|
Kevin Millikin (Google)
2017/03/31 12:23:41
h ==> helper
|
| + DartTypeTranslator* type_translator) |
| + : builder_(builder), |
| + isolate_(Isolate::Current()), |
| + zone_(zone), |
| + translation_helper_(*h), |
| + // type_translator_(*type_translator), |
|
Kevin Millikin (Google)
2017/03/31 12:23:41
Why this commented out code?
|
| + script_(Script::Handle( |
| + zone, |
| + builder == NULL ? Script::null() |
| + : builder_->parsed_function()->function().script())), |
| + result_(Instance::Handle(zone)) {} |
| + |
| + |
| +Instance& StreamingConstantEvaluator::EvaluateExpression() { |
| + intptr_t offset = builder_->ReaderOffset(); |
| + if (!GetCachedConstant(offset, &result_)) { |
| + uint8_t payload = 0; |
| + Tag tag = builder_->ReadTag(&payload); |
| + switch (tag) { |
| + case kDoubleLiteral: |
| + EvaluateDoubleLiteral(); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + |
| + CacheConstantValue(offset, result_); |
| + } |
| + // We return a new `ZoneHandle` here on purpose: The intermediate language |
| + // instructions do not make a copy of the handle, so we do it. |
| + return dart::Instance::ZoneHandle(Z, result_.raw()); |
|
Kevin Millikin (Google)
2017/03/31 12:23:41
I guess you just copied this, but it doesn't need
|
| +} |
| + |
| +void StreamingConstantEvaluator::EvaluateDoubleLiteral() { |
| + int str_index = builder_->ReadUInt(); |
| + result_ = dart::Double::New(builder_->DartString(str_index), Heap::kOld); |
|
Kevin Millikin (Google)
2017/03/31 12:23:41
I don't think we need dart:: here either.
|
| + result_ = H.Canonicalize(result_); |
| +} |
| + |
| +bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset, |
| + Instance* value) { |
| + if (builder_ == NULL) return false; |
| + |
| + const Function& function = builder_->parsed_function()->function(); |
| + if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
| + // Don't cache constants in initializer expressions. They get |
| + // evaluated only once. |
| + return false; |
| + } |
| + |
| + bool is_present = false; |
| + ASSERT(!script_.InVMHeap()); |
| + if (script_.compile_time_constants() == Array::null()) { |
| + return false; |
| + } |
| + KernelConstantsMap constants(script_.compile_time_constants()); |
| + *value ^= constants.GetOrNull(kernel_offset, &is_present); |
| + // Mutator compiler thread may add constants while background compiler |
| + // is running, and thus change the value of 'compile_time_constants'; |
| + // do not assert that 'compile_time_constants' has not changed. |
| + constants.Release(); |
| + if (FLAG_compiler_stats && is_present) { |
| + H.thread()->compiler_stats()->num_const_cache_hits++; |
| + } |
| + return is_present; |
| +} |
| + |
| + |
| +void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset, |
| + const Instance& value) { |
| + ASSERT(Thread::Current()->IsMutatorThread()); |
| + |
| + if (builder_ == NULL) return; |
| + |
| + const Function& function = builder_->parsed_function()->function(); |
| + if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
| + // Don't cache constants in initializer expressions. They get |
| + // evaluated only once. |
| + return; |
| + } |
| + const intptr_t kInitialConstMapSize = 16; |
| + ASSERT(!script_.InVMHeap()); |
| + if (script_.compile_time_constants() == Array::null()) { |
| + const Array& array = Array::Handle( |
| + HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew)); |
| + script_.set_compile_time_constants(array); |
| + } |
| + KernelConstantsMap constants(script_.compile_time_constants()); |
| + constants.InsertNewOrGetValue(kernel_offset, value); |
| + script_.set_compile_time_constants(constants.Release()); |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::BuildAt(intptr_t kernel_offset) { |
| - reader_->set_offset(kernel_offset); |
| + SetOffset(kernel_offset); |
| uint8_t payload = 0; |
| - Tag tag = reader_->ReadTag(&payload); |
| + Tag tag = ReadTag(&payload); |
| switch (tag) { |
| case kInvalidExpression: |
| return BuildInvalidExpression(); |
| @@ -98,8 +195,8 @@ Fragment StreamingFlowGraphBuilder::BuildAt(intptr_t kernel_offset) { |
| return BuildIntLiteral(true); |
| case kPositiveIntLiteral: |
| return BuildIntLiteral(false); |
| - // case kDoubleLiteral: |
| - // return DoubleLiteral::ReadFrom(reader_); |
| + case kDoubleLiteral: |
| + return BuildDoubleLiteral(); |
| case kTrueLiteral: |
| return BuildBoolLiteral(true); |
| case kFalseLiteral: |
| @@ -121,7 +218,7 @@ intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) { |
| reader_->set_offset(4); // Skip kMagicProgramFile - now at string table. |
| string_table_size_ = ReadListLength(); |
| string_table_offsets_ = new intptr_t[string_table_size_]; |
| - string_table_offsets_[0] = reader_->offset(); |
| + string_table_offsets_[0] = ReaderOffset(); |
| string_table_entries_read_ = 1; |
| } |
| @@ -129,16 +226,28 @@ intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) { |
| --string_table_entries_read_; |
| reader_->set_offset(string_table_offsets_[string_table_entries_read_]); |
| for (; string_table_entries_read_ < index; ++string_table_entries_read_) { |
| - string_table_offsets_[string_table_entries_read_] = reader_->offset(); |
| + string_table_offsets_[string_table_entries_read_] = ReaderOffset(); |
| uint32_t bytes = ReadUInt(); |
| - reader_->set_offset(reader_->offset() + bytes); |
| + SkipBytes(bytes); |
| } |
| - string_table_offsets_[string_table_entries_read_] = reader_->offset(); |
| + string_table_offsets_[string_table_entries_read_] = ReaderOffset(); |
| ++string_table_entries_read_; |
| return string_table_offsets_[index]; |
| } |
| +intptr_t StreamingFlowGraphBuilder::ReaderOffset() { |
| + return reader_->offset(); |
| +} |
| + |
| +void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) { |
| + reader_->set_offset(offset); |
| +} |
| + |
| +void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) { |
| + reader_->set_offset(ReaderOffset() + bytes); |
| +} |
| + |
| uint32_t StreamingFlowGraphBuilder::ReadUInt() { |
| return reader_->ReadUInt(); |
| } |
| @@ -151,6 +260,10 @@ TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) { |
| return reader_->ReadPosition(record); |
| } |
| +Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) { |
| + return reader_->ReadTag(payload); |
| +} |
| + |
| CatchBlock* StreamingFlowGraphBuilder::catch_block() { |
| return flow_graph_builder_->catch_block_; |
| } |
| @@ -159,6 +272,32 @@ ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() { |
| return flow_graph_builder_->scopes_; |
| } |
| +ParsedFunction* StreamingFlowGraphBuilder::parsed_function() { |
| + return flow_graph_builder_->parsed_function_; |
| +} |
| + |
| +dart::String& StreamingFlowGraphBuilder::DartSymbol(intptr_t str_index) { |
| + intptr_t savedOffset = ReaderOffset(); |
| + |
| + SetOffset(GetStringTableOffset(str_index)); |
| + uint32_t bytes = ReadUInt(); |
| + const uint8_t* data = &reader_->buffer()[ReaderOffset()]; |
| + |
| + SetOffset(savedOffset); |
| + return H.DartSymbol(data, bytes); |
| +} |
| + |
| +dart::String& StreamingFlowGraphBuilder::DartString(intptr_t str_index) { |
| + intptr_t savedOffset = ReaderOffset(); |
| + |
| + SetOffset(GetStringTableOffset(str_index)); |
| + uint32_t bytes = ReadUInt(); |
| + const uint8_t* data = &reader_->buffer()[ReaderOffset()]; |
| + |
| + SetOffset(savedOffset); |
| + return H.DartString(data, bytes); |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) { |
| return flow_graph_builder_->DebugStepCheck(position); |
| } |
| @@ -212,15 +351,8 @@ Fragment StreamingFlowGraphBuilder::BuildRethrow() { |
| } |
| Fragment StreamingFlowGraphBuilder::BuildStringLiteral() { |
| - int str_index = ReadUInt(); |
| - intptr_t savedOffset = reader_->offset(); |
| - |
| - reader_->set_offset(GetStringTableOffset(str_index)); |
| - uint32_t bytes = ReadUInt(); |
| - const uint8_t* data = &reader_->buffer()[reader_->offset()]; |
| - |
| - reader_->set_offset(savedOffset); |
| - return Constant(H.DartSymbol(data, bytes)); |
| + intptr_t str_index = ReadUInt(); |
| + return Constant(DartSymbol(str_index)); |
| } |
| Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload) { |
| @@ -233,6 +365,11 @@ Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative) { |
| return IntConstant(value); |
| } |
| +Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral() { |
| + SkipBytes(-1); // EvaluateExpression needs the tag. |
| + return Constant(constant_evaluator_.EvaluateExpression()); |
| +} |
| + |
| Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value) { |
| return Constant(Bool::Get(value)); |
| } |