Remove bytecode mode from the VM

Change-Id: Ief167b7ffc128105a03cc225ab750234c9a6a7a0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/169147
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Alexander Markov
2020-10-28 17:42:35 +00:00
committed by commit-bot@chromium.org
parent c877d5bf3e
commit 7588ed86de
150 changed files with 1958 additions and 21079 deletions
+4 -5
View File
@@ -732,10 +732,10 @@ Future _processLoadRequest(request) async {
final bool enableAsserts = request[9];
final List<String> experimentalFlags =
request[10] != null ? request[10].cast<String>() : null;
final String packageConfig = request[12];
final String multirootFilepaths = request[13];
final String multirootScheme = request[14];
final String workingDirectory = request[15];
final String packageConfig = request[11];
final String multirootFilepaths = request[12];
final String multirootScheme = request[13];
final String workingDirectory = request[14];
Uri platformKernelPath = null;
List<int> platformKernel = null;
@@ -981,7 +981,6 @@ Future trainInternal(String scriptUri, String platformKernelPath) async {
false /* suppress warnings */,
false /* enable asserts */,
null /* experimental_flags */,
null /* unused */,
null /* package_config */,
null /* multirootFilepaths */,
null /* multirootScheme */,
-8
View File
@@ -125,7 +125,6 @@ static const char* kSnapshotKindNames[] = {
V(compile_all, compile_all) \
V(help, help) \
V(obfuscate, obfuscate) \
V(read_all_bytecode, read_all_bytecode) \
V(strip, strip) \
V(verbose, verbose) \
V(version, version)
@@ -390,13 +389,6 @@ static void MaybeLoadExtraInputs(const CommandLineOptions& inputs) {
}
static void MaybeLoadCode() {
if (read_all_bytecode &&
((snapshot_kind == kCore) || (snapshot_kind == kCoreJIT) ||
(snapshot_kind == kApp) || (snapshot_kind == kAppJIT))) {
Dart_Handle result = Dart_ReadAllBytecode();
CHECK_RESULT(result);
}
if (compile_all &&
((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
Dart_Handle result = Dart_CompileAll();
-2
View File
@@ -178,8 +178,6 @@ DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id);
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll();
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode();
/**
* Finalizes all classes.
*/
+13 -17
View File
@@ -31,25 +31,21 @@ static ScriptPtr FindScript(DartFrameIterator* iterator) {
ASSERT(!assert_error_class.IsNull());
bool hit_assertion_error = false;
for (; stack_frame != NULL; stack_frame = iterator->NextFrame()) {
if (stack_frame->is_interpreted()) {
func = stack_frame->LookupDartFunction();
} else {
code = stack_frame->LookupDartCode();
if (code.is_optimized()) {
InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
while (!inlined_iterator.Done()) {
func = inlined_iterator.function();
if (hit_assertion_error) {
return func.script();
}
ASSERT(!hit_assertion_error);
hit_assertion_error = (func.Owner() == assert_error_class.raw());
inlined_iterator.Advance();
code = stack_frame->LookupDartCode();
if (code.is_optimized()) {
InlinedFunctionsIterator inlined_iterator(code, stack_frame->pc());
while (!inlined_iterator.Done()) {
func = inlined_iterator.function();
if (hit_assertion_error) {
return func.script();
}
continue;
} else {
func = code.function();
ASSERT(!hit_assertion_error);
hit_assertion_error = (func.Owner() == assert_error_class.raw());
inlined_iterator.Advance();
}
continue;
} else {
func = code.function();
}
ASSERT(!func.IsNull());
if (hit_assertion_error) {
+1 -28
View File
@@ -306,36 +306,9 @@ DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) {
return Integer::New(SizeOf(type_arg, zone));
}
// Static invocations to this method are translated directly in streaming FGB
// and bytecode FGB. However, we can still reach this entrypoint in the bytecode
// interpreter.
// Static invocations to this method are translated directly in streaming FGB.
DEFINE_NATIVE_ENTRY(Ffi_asFunctionInternal, 2, 1) {
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
UNREACHABLE();
#else
ASSERT(FLAG_enable_interpreter);
GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
GET_NATIVE_TYPE_ARGUMENT(dart_type, arguments->NativeTypeArgAt(0));
GET_NATIVE_TYPE_ARGUMENT(native_type, arguments->NativeTypeArgAt(1));
const Function& dart_signature =
Function::Handle(zone, Type::Cast(dart_type).signature());
const Function& native_signature =
Function::Handle(zone, Type::Cast(native_type).signature());
const Function& function = Function::Handle(
compiler::ffi::TrampolineFunction(dart_signature, native_signature));
// Set the c function pointer in the context of the closure rather than in
// the function so that we can reuse the function for each c function with
// the same signature.
const Context& context = Context::Handle(Context::New(1));
context.SetAt(0, pointer);
return Closure::New(Object::null_type_arguments(),
Object::null_type_arguments(), function, context,
Heap::kOld);
#endif
}
DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) {
-74
View File
@@ -456,76 +456,6 @@ static InstancePtr CreateLibraryDependencyMirror(Thread* thread,
prefix_name, is_import, is_deferred);
}
static GrowableObjectArrayPtr CreateBytecodeLibraryDependencies(
Thread* thread,
const Library& lib,
const Instance& lib_mirror) {
ASSERT(lib.is_declared_in_bytecode());
// Make sure top level class (containing annotations) is fully loaded.
lib.EnsureTopLevelClassIsFinalized();
const auto& deps = GrowableObjectArray::Handle(GrowableObjectArray::New());
Array& metadata = Array::Handle(lib.GetExtendedMetadata(lib, 1));
if (metadata.Length() == 0) {
return deps.raw();
}
// Library has the only element in the extended metadata.
metadata ^= metadata.At(0);
if (metadata.IsNull()) {
return deps.raw();
}
auto& desc = Array::Handle();
auto& target_uri = String::Handle();
auto& importee = Library::Handle();
auto& is_export = Bool::Handle();
auto& is_deferred = Bool::Handle();
auto& prefix_name = String::Handle();
auto& show_names = Array::Handle();
auto& hide_names = Array::Handle();
auto& dep_metadata = Instance::Handle();
auto& dep = Instance::Handle();
const auto& no_prefix = LibraryPrefix::Handle();
for (intptr_t i = 0, n = metadata.Length(); i < n; ++i) {
desc ^= metadata.At(i);
// Each dependency is represented as an array with the following layout:
// [0] = target library URI (String)
// [1] = is_export (bool)
// [2] = is_deferred (bool)
// [3] = prefix (String or null)
// [4] = list of show names (List<String>)
// [5] = list of hide names (List<String>)
// [6] = annotations
// The library dependencies are encoded by getLibraryAnnotations(),
// pkg/vm/lib/bytecode/gen_bytecode.dart.
target_uri ^= desc.At(0);
is_export ^= desc.At(1);
is_deferred ^= desc.At(2);
prefix_name ^= desc.At(3);
show_names ^= desc.At(4);
hide_names ^= desc.At(5);
dep_metadata ^= desc.At(6);
importee = Library::LookupLibrary(thread, target_uri);
if (importee.IsNull()) {
continue;
}
ASSERT(importee.Loaded());
dep = CreateLibraryDependencyMirror(
thread, lib_mirror, importee, show_names, hide_names, dep_metadata,
no_prefix, prefix_name, !is_export.value(), is_deferred.value());
if (!dep.IsNull()) {
deps.Add(dep);
}
}
return deps.raw();
}
DEFINE_NATIVE_ENTRY(LibraryMirror_fromPrefix, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(LibraryPrefix, prefix,
arguments->NativeArgAt(0));
@@ -541,10 +471,6 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_libraryDependencies, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
const Library& lib = Library::Handle(ref.GetLibraryReferent());
if (lib.is_declared_in_bytecode()) {
return CreateBytecodeLibraryDependencies(thread, lib, lib_mirror);
}
Array& ports = Array::Handle();
Namespace& ns = Namespace::Handle();
Instance& dep = Instance::Handle();
+4 -14
View File
@@ -141,7 +141,7 @@ DEFINE_NATIVE_ENTRY(StackTrace_asyncStackTraceHelper, 0, 1) {
if (!FLAG_causal_async_stacks) {
// If causal async stacks are not enabled we should recognize this method
// and never call to the NOP runtime.
// See kernel_to_il.cc/bytecode_reader.cc/interpreter.cc.
// See kernel_to_il.cc.
UNREACHABLE();
}
#if !defined(PRODUCT)
@@ -180,7 +180,6 @@ static void AppendFrames(const GrowableObjectArray& code_list,
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL); // We expect to find a dart invocation frame.
Code& code = Code::Handle(zone);
Bytecode& bytecode = Bytecode::Handle(zone);
Smi& offset = Smi::Handle(zone);
for (; frame != NULL; frame = frames.NextFrame()) {
if (!frame->IsDartFrame()) {
@@ -191,18 +190,9 @@ static void AppendFrames(const GrowableObjectArray& code_list,
continue;
}
if (frame->is_interpreted()) {
bytecode = frame->LookupDartBytecode();
if (bytecode.function() == Function::null()) {
continue;
}
offset = Smi::New(frame->pc() - bytecode.PayloadStart());
code_list.Add(bytecode);
} else {
code = frame->LookupDartCode();
offset = Smi::New(frame->pc() - code.PayloadStart());
code_list.Add(code);
}
code = frame->LookupDartCode();
offset = Smi::New(frame->pc() - code.PayloadStart());
code_list.Add(code);
pc_offset_list.Add(offset);
}
}
+1 -1
View File
@@ -178,7 +178,7 @@ DEFINE_NATIVE_ENTRY(TypedData_setRange, 0, 7) {
}
// Native methods for typed data allocation are recognized and implemented
// both in FlowGraphBuilder::BuildGraphOfRecognizedMethod and interpreter.
// in FlowGraphBuilder::BuildGraphOfRecognizedMethod.
// These bodies exist only to assert that they are not used.
#define TYPED_DATA_NEW(name) \
DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 0, 2) { \
@@ -277,21 +277,6 @@ class FunctionViewElement extends CustomElement implements Renderable {
]
]);
}
if (_function.bytecode != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'bytecode',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new CodeRefElement(_isolate, _function.bytecode!, queue: _r.queue)
.element,
]
]);
}
members.add(new DivElement()
..classes = ['memberItem']
..text = ' ');
@@ -87,9 +87,6 @@ abstract class ServiceFunction extends Object implements FunctionRef {
/// [optional]
CodeRef? get unoptimizedCode;
/// [optional]
CodeRef? get bytecode;
/// [optional]
FieldRef? get field;
int? get usageCounter;
@@ -3165,7 +3165,6 @@ class ServiceFunction extends HeapObject implements M.ServiceFunction {
SourceLocation? location;
Code? code;
Code? unoptimizedCode;
Code? bytecode;
bool? isOptimizable;
bool? isInlinable;
bool? hasIntrinsic;
@@ -3224,7 +3223,6 @@ class ServiceFunction extends HeapObject implements M.ServiceFunction {
isInlinable = map['_inlinable'];
isRecognized = map['_recognized'];
unoptimizedCode = map['_unoptimizedCode'];
bytecode = map['_bytecode'];
deoptimizations = map['_deoptimizations'];
usageCounter = map['_usageCounter'];
icDataArray = map['_icDataArray'];
@@ -577,7 +577,7 @@ IsolateTest checkRecordedStops(
expectedStops = removeAdjacentDuplicates(expectedStops);
}
// Single stepping in interpreted bytecode may record extra stops.
// Single stepping may record extra stops.
// Allow the extra ones as long as the expected ones are recorded.
int i = 0;
int j = 0;
@@ -276,21 +276,6 @@ class FunctionViewElement extends CustomElement implements Renderable {
]
]);
}
if (_function.bytecode != null) {
members.add(new DivElement()
..classes = ['memberItem']
..children = <Element>[
new DivElement()
..classes = ['memberName']
..text = 'bytecode',
new DivElement()
..classes = ['memberName']
..children = <Element>[
new CodeRefElement(_isolate, _function.bytecode, queue: _r.queue)
.element,
]
]);
}
members.add(new DivElement()
..classes = ['memberItem']
..text = ' ');
@@ -87,9 +87,6 @@ abstract class ServiceFunction extends Object implements FunctionRef {
/// [optional]
CodeRef get unoptimizedCode;
/// [optional]
CodeRef get bytecode;
/// [optional]
FieldRef get field;
int get usageCounter;
@@ -3178,7 +3178,6 @@ class ServiceFunction extends HeapObject implements M.ServiceFunction {
SourceLocation location;
Code code;
Code unoptimizedCode;
Code bytecode;
bool isOptimizable;
bool isInlinable;
bool hasIntrinsic;
@@ -3237,7 +3236,6 @@ class ServiceFunction extends HeapObject implements M.ServiceFunction {
isInlinable = map['_inlinable'];
isRecognized = map['_recognized'];
unoptimizedCode = map['_unoptimizedCode'];
bytecode = map['_bytecode'];
deoptimizations = map['_deoptimizations'];
usageCounter = map['_usageCounter'];
icDataArray = map['_icDataArray'];
@@ -577,7 +577,7 @@ IsolateTest checkRecordedStops(
expectedStops = removeAdjacentDuplicates(expectedStops);
}
// Single stepping in interpreted bytecode may record extra stops.
// Single stepping may record extra stops.
// Allow the extra ones as long as the expected ones are recorded.
int i = 0;
int j = 0;
@@ -28,7 +28,7 @@ class TargetCalls {
int unchecked = 0;
// Leave a little room for some cases which always use the checked entry, like
// lazy compile stub or interpreter warm-up.
// lazy compile stub.
static const int wiggle = 10;
void expectChecked(int iterations) {
@@ -1,35 +0,0 @@
// Copyright (c) 2019, 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.
//
// VMOptions=--optimization-counter-threshold=5 --use-bytecode-compiler
//
// Test that block merging takes phis into account.
//
// The problem only reproduces with bytecode compiler (--use-bytecode-compiler)
// as bytecode doesn't have backward branches for the redundant loops.
// OSR handling code inserts Phi instructions to JoinEntry
// even when there is only one predecessor. This results in a flow graph
// suitable for block merging with a successor block containing Phi.
import 'package:expect/expect.dart';
void testBottomUpInference() {
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
}
main() {
testBottomUpInference();
}
@@ -28,7 +28,7 @@ class TargetCalls {
int unchecked = 0;
// Leave a little room for some cases which always use the checked entry, like
// lazy compile stub or interpreter warm-up.
// lazy compile stub.
static const int wiggle = 10;
void expectChecked(int iterations) {
@@ -1,35 +0,0 @@
// Copyright (c) 2019, 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.
//
// VMOptions=--optimization-counter-threshold=5 --use-bytecode-compiler
//
// Test that block merging takes phis into account.
//
// The problem only reproduces with bytecode compiler (--use-bytecode-compiler)
// as bytecode doesn't have backward branches for the redundant loops.
// OSR handling code inserts Phi instructions to JoinEntry
// even when there is only one predecessor. This results in a flow graph
// suitable for block merging with a successor block containing Phi.
import 'package:expect/expect.dart';
void testBottomUpInference() {
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
Expect.type<List<int>>([for (; false;) 1]);
}
main() {
testBottomUpInference();
}
+2 -8
View File
@@ -313,7 +313,6 @@ static void StackFrame_accessFrame(Dart_NativeArguments args) {
TransitionNativeToVM transition(thread);
const int kNumIterations = 100;
Code& code = Code::Handle(thread->zone());
Bytecode& bytecode = Bytecode::Handle(thread->zone());
for (int i = 0; i < kNumIterations; i++) {
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
StackFrameIterator::kNoCrossThreadIteration);
@@ -323,13 +322,8 @@ static void StackFrame_accessFrame(Dart_NativeArguments args) {
code = frame->LookupDartCode();
EXPECT(code.function() == Function::null());
} else if (frame->IsDartFrame()) {
if (frame->is_interpreted()) {
bytecode = frame->LookupDartBytecode();
EXPECT(bytecode.function() != Function::null());
} else {
code = frame->LookupDartCode();
EXPECT(code.function() != Function::null());
}
code = frame->LookupDartCode();
EXPECT(code.function() != Function::null());
}
frame = frames.NextFrame();
}
+5 -41
View File
@@ -12,7 +12,6 @@
#include "vm/flags.h"
#include "vm/hash_table.h"
#include "vm/heap/heap.h"
#include "vm/interpreter.h"
#include "vm/isolate.h"
#include "vm/kernel_loader.h"
#include "vm/log.h"
@@ -198,19 +197,14 @@ bool ClassFinalizer::ProcessPendingClasses() {
#if defined(DEBUG)
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
ASSERT(cls.is_declared_in_bytecode() || cls.is_declaration_loaded());
ASSERT(cls.is_declaration_loaded());
}
#endif
// Finalize types in all classes.
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
if (cls.is_declared_in_bytecode()) {
cls.EnsureDeclarationLoaded();
ASSERT(cls.is_type_finalized());
} else {
FinalizeTypesInClass(cls);
}
FinalizeTypesInClass(cls);
}
// Clear pending classes array.
@@ -1118,14 +1112,9 @@ void ClassFinalizer::FinalizeClass(const Class& cls) {
#if !defined(DART_PRECOMPILED_RUNTIME)
// If loading from a kernel, make sure that the class is fully loaded.
ASSERT(cls.IsTopLevel() || cls.is_declared_in_bytecode() ||
(cls.kernel_offset() > 0));
ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0));
if (!cls.is_loaded()) {
if (cls.is_declared_in_bytecode()) {
kernel::BytecodeReader::FinishClassLoading(cls);
} else {
kernel::KernelLoader::FinishLoading(cls);
}
kernel::KernelLoader::FinishLoading(cls);
if (cls.is_finalized()) {
return;
}
@@ -1264,7 +1253,7 @@ void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) {
ASSERT(!sentinel.IsNull());
sentinel.SetStaticValue(enum_value, true);
ASSERT(enum_cls.is_declared_in_bytecode() || enum_cls.kernel_offset() > 0);
ASSERT(enum_cls.kernel_offset() > 0);
Error& error = Error::Handle(zone);
for (intptr_t i = 0; i < fields.Length(); i++) {
field = Field::RawCast(fields.At(i));
@@ -1712,14 +1701,6 @@ void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
#ifdef DART_PRECOMPILED_RUNTIME
UNREACHABLE();
#else
Thread* mutator_thread = Isolate::Current()->mutator_thread();
if (mutator_thread != nullptr) {
Interpreter* interpreter = mutator_thread->interpreter();
if (interpreter != nullptr) {
interpreter->ClearLookupCache();
}
}
auto const thread = Thread::Current();
auto const isolate = thread->isolate();
StackZone stack_zone(thread);
@@ -1730,7 +1711,6 @@ void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
public:
ClearCodeVisitor(Zone* zone, bool force)
: force_(force),
bytecode_(Bytecode::Handle(zone)),
pool_(ObjectPool::Handle(zone)),
entry_(Object::Handle(zone)) {}
@@ -1741,28 +1721,12 @@ void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
}
void VisitFunction(const Function& function) {
bytecode_ = function.bytecode();
if (!bytecode_.IsNull()) {
pool_ = bytecode_.object_pool();
for (intptr_t i = 0; i < pool_.Length(); i++) {
ObjectPool::EntryType entry_type = pool_.TypeAt(i);
if (entry_type != ObjectPool::EntryType::kTaggedObject) {
continue;
}
entry_ = pool_.ObjectAt(i);
if (entry_.IsSubtypeTestCache()) {
SubtypeTestCache::Cast(entry_).Reset();
}
}
}
function.ClearCode();
function.ClearICDataArray();
}
private:
const bool force_;
Bytecode& bytecode_;
ObjectPool& pool_;
Object& entry_;
};
-2
View File
@@ -31,7 +31,6 @@ typedef uint16_t ClassIdTagType;
V(Namespace) \
V(KernelProgramInfo) \
V(Code) \
V(Bytecode) \
V(Instructions) \
V(InstructionsSection) \
V(ObjectPool) \
@@ -42,7 +41,6 @@ typedef uint16_t ClassIdTagType;
V(ExceptionHandlers) \
V(Context) \
V(ContextScope) \
V(ParameterTypeCheck) \
V(SingleTargetCache) \
V(UnlinkedCall) \
V(MonomorphicSmiableCall) \
+13 -230
View File
@@ -250,7 +250,7 @@ class ClassSerializationCluster : public SerializationCluster {
s->UnexpectedObject(cls, "Class with non mode agnostic constants");
}
if (s->kind() != Snapshot::kFullAOT) {
s->Write<uint32_t>(cls->ptr()->binary_declaration_);
s->Write<uint32_t>(cls->ptr()->kernel_offset_);
}
s->Write<int32_t>(Class::target_instance_size_in_words(cls));
s->Write<int32_t>(Class::target_next_field_offset_in_words(cls));
@@ -325,7 +325,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
cls->ptr()->id_ = class_id;
#if !defined(DART_PRECOMPILED_RUNTIME)
if (d->kind() != Snapshot::kFullAOT) {
cls->ptr()->binary_declaration_ = d->Read<uint32_t>();
cls->ptr()->kernel_offset_ = d->Read<uint32_t>();
}
#endif
if (!IsInternalVMdefinedClassId(class_id)) {
@@ -372,7 +372,7 @@ class ClassDeserializationCluster : public DeserializationCluster {
#if !defined(DART_PRECOMPILED_RUNTIME)
if (d->kind() != Snapshot::kFullAOT) {
cls->ptr()->binary_declaration_ = d->Read<uint32_t>();
cls->ptr()->kernel_offset_ = d->Read<uint32_t>();
}
#endif
cls->ptr()->host_instance_size_in_words_ = d->Read<int32_t>();
@@ -598,13 +598,10 @@ class FunctionSerializationCluster : public SerializationCluster {
objects_.Add(func);
PushFromTo(func);
if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
} else if (kind == Snapshot::kFullAOT) {
if (kind == Snapshot::kFullAOT) {
s->Push(func->ptr()->code_);
} else if (kind == Snapshot::kFullJIT) {
NOT_IN_PRECOMPILED(s->Push(func->ptr()->unoptimized_code_));
NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
s->Push(func->ptr()->code_);
s->Push(func->ptr()->ic_data_array_);
}
@@ -627,13 +624,10 @@ class FunctionSerializationCluster : public SerializationCluster {
FunctionPtr func = objects_[i];
AutoTraceObjectName(func, MakeDisambiguatedFunctionName(s, func));
WriteFromTo(func);
if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
} else if (kind == Snapshot::kFullAOT) {
if (kind == Snapshot::kFullAOT) {
WriteField(func, code_);
} else if (s->kind() == Snapshot::kFullJIT) {
NOT_IN_PRECOMPILED(WriteField(func, unoptimized_code_));
NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
WriteField(func, code_);
WriteField(func, ic_data_array_);
}
@@ -641,7 +635,7 @@ class FunctionSerializationCluster : public SerializationCluster {
if (kind != Snapshot::kFullAOT) {
s->WriteTokenPosition(func->ptr()->token_pos_);
s->WriteTokenPosition(func->ptr()->end_token_pos_);
s->Write<uint32_t>(func->ptr()->binary_declaration_);
s->Write<uint32_t>(func->ptr()->kernel_offset_);
}
s->Write<uint32_t>(func->ptr()->packed_fields_);
@@ -694,16 +688,11 @@ class FunctionDeserializationCluster : public DeserializationCluster {
Function::InstanceSize());
ReadFromTo(func);
if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
static_cast<BytecodePtr>(d->ReadRef()));
} else if (kind == Snapshot::kFullAOT) {
if (kind == Snapshot::kFullAOT) {
func->ptr()->code_ = static_cast<CodePtr>(d->ReadRef());
} else if (kind == Snapshot::kFullJIT) {
NOT_IN_PRECOMPILED(func->ptr()->unoptimized_code_ =
static_cast<CodePtr>(d->ReadRef()));
NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
static_cast<BytecodePtr>(d->ReadRef()));
func->ptr()->code_ = static_cast<CodePtr>(d->ReadRef());
func->ptr()->ic_data_array_ = static_cast<ArrayPtr>(d->ReadRef());
}
@@ -717,7 +706,7 @@ class FunctionDeserializationCluster : public DeserializationCluster {
if (kind != Snapshot::kFullAOT) {
func->ptr()->token_pos_ = d->ReadTokenPosition();
func->ptr()->end_token_pos_ = d->ReadTokenPosition();
func->ptr()->binary_declaration_ = d->Read<uint32_t>();
func->ptr()->kernel_offset_ = d->Read<uint32_t>();
}
func->ptr()->unboxed_parameters_info_.Reset();
#endif
@@ -1143,7 +1132,7 @@ class FieldSerializationCluster : public SerializationCluster {
s->WriteCid(field->ptr()->guarded_cid_);
s->WriteCid(field->ptr()->is_nullable_);
s->Write<int8_t>(field->ptr()->static_type_exactness_state_);
s->Write<uint32_t>(field->ptr()->binary_declaration_);
s->Write<uint32_t>(field->ptr()->kernel_offset_);
}
s->Write<uint16_t>(field->ptr()->kind_bits_);
@@ -1213,7 +1202,7 @@ class FieldDeserializationCluster : public DeserializationCluster {
field->ptr()->is_nullable_ = d->ReadCid();
field->ptr()->static_type_exactness_state_ = d->Read<int8_t>();
#if !defined(DART_PRECOMPILED_RUNTIME)
field->ptr()->binary_declaration_ = d->Read<uint32_t>();
field->ptr()->kernel_offset_ = d->Read<uint32_t>();
#endif
}
field->ptr()->kind_bits_ = d->Read<uint16_t>();
@@ -1359,7 +1348,7 @@ class LibrarySerializationCluster : public SerializationCluster {
s->Write<int8_t>(lib->ptr()->load_state_);
s->Write<uint8_t>(lib->ptr()->flags_);
if (s->kind() != Snapshot::kFullAOT) {
s->Write<uint32_t>(lib->ptr()->binary_declaration_);
s->Write<uint32_t>(lib->ptr()->kernel_offset_);
}
}
}
@@ -1398,7 +1387,7 @@ class LibraryDeserializationCluster : public DeserializationCluster {
LibraryLayout::InFullSnapshotBit::update(true, d->Read<uint8_t>());
#if !defined(DART_PRECOMPILED_RUNTIME)
if (d->kind() != Snapshot::kFullAOT) {
lib->ptr()->binary_declaration_ = d->Read<uint32_t>();
lib->ptr()->kernel_offset_ = d->Read<uint32_t>();
}
#endif
}
@@ -1982,88 +1971,6 @@ class CodeDeserializationCluster : public DeserializationCluster {
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class BytecodeSerializationCluster : public SerializationCluster {
public:
BytecodeSerializationCluster() : SerializationCluster("Bytecode") {}
virtual ~BytecodeSerializationCluster() {}
void Trace(Serializer* s, ObjectPtr object) {
BytecodePtr bytecode = Bytecode::RawCast(object);
objects_.Add(bytecode);
PushFromTo(bytecode);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kBytecodeCid);
const intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
BytecodePtr bytecode = objects_[i];
s->AssignRef(bytecode);
}
}
void WriteFill(Serializer* s) {
ASSERT(s->kind() != Snapshot::kFullAOT);
const intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
BytecodePtr bytecode = objects_[i];
s->Write<int32_t>(bytecode->ptr()->instructions_size_);
WriteFromTo(bytecode);
s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_);
}
}
private:
GrowableArray<BytecodePtr> objects_;
};
class BytecodeDeserializationCluster : public DeserializationCluster {
public:
BytecodeDeserializationCluster() : DeserializationCluster("Bytecode") {}
virtual ~BytecodeDeserializationCluster() {}
void ReadAlloc(Deserializer* d, bool is_canonical) {
start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
const intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(AllocateUninitialized(old_space, Bytecode::InstanceSize()));
}
stop_index_ = d->next_index();
}
void ReadFill(Deserializer* d, bool is_canonical) {
ASSERT(d->kind() != Snapshot::kFullAOT);
for (intptr_t id = start_index_; id < stop_index_; id++) {
BytecodePtr bytecode = static_cast<BytecodePtr>(d->Ref(id));
Deserializer::InitializeHeader(bytecode, kBytecodeCid,
Bytecode::InstanceSize());
bytecode->ptr()->instructions_ = 0;
bytecode->ptr()->instructions_size_ = d->Read<int32_t>();
ReadFromTo(bytecode);
bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
bytecode->ptr()->local_variables_binary_offset_ = d->Read<int32_t>();
}
}
void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
Bytecode& bytecode = Bytecode::Handle(d->zone());
ExternalTypedData& binary = ExternalTypedData::Handle(d->zone());
for (intptr_t i = start_index_; i < stop_index_; i++) {
bytecode ^= refs.At(i);
binary = bytecode.GetBinary(d->zone());
bytecode.set_instructions(reinterpret_cast<uword>(
binary.DataAddr(bytecode.instructions_binary_offset())));
}
}
};
class ObjectPoolSerializationCluster : public SerializationCluster {
public:
ObjectPoolSerializationCluster() : SerializationCluster("ObjectPool") {}
@@ -2077,8 +1984,7 @@ class ObjectPoolSerializationCluster : public SerializationCluster {
uint8_t* entry_bits = pool->ptr()->entry_bits();
for (intptr_t i = 0; i < length; i++) {
auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
if ((entry_type == ObjectPool::EntryType::kTaggedObject) ||
(entry_type == ObjectPool::EntryType::kNativeEntryData)) {
if (entry_type == ObjectPool::EntryType::kTaggedObject) {
s->Push(pool->ptr()->data()[i].raw_obj_);
}
}
@@ -2125,22 +2031,6 @@ class ObjectPoolSerializationCluster : public SerializationCluster {
s->Write<intptr_t>(entry.raw_value_);
break;
}
case ObjectPool::EntryType::kNativeEntryData: {
ObjectPtr raw = entry.raw_obj_;
TypedDataPtr raw_data = static_cast<TypedDataPtr>(raw);
// kNativeEntryData object pool entries are for linking natives for
// the interpreter. Before writing these entries into the snapshot,
// we need to unlink them by nulling out the 'trampoline' and
// 'native_function' fields.
NativeEntryData::Payload* payload =
NativeEntryData::FromTypedArray(raw_data);
if (payload->kind == MethodRecognizer::kUnknown) {
payload->trampoline = NULL;
payload->native_function = NULL;
}
s->WriteElementRef(raw, j);
break;
}
case ObjectPool::EntryType::kNativeFunction:
case ObjectPool::EntryType::kNativeFunctionWrapper: {
// Write nothing. Will initialize with the lazy link entry.
@@ -2187,7 +2077,6 @@ class ObjectPoolDeserializationCluster : public DeserializationCluster {
pool->ptr()->entry_bits()[j] = entry_bits;
ObjectPoolLayout::Entry& entry = pool->ptr()->data()[j];
switch (ObjectPool::TypeBits::decode(entry_bits)) {
case ObjectPool::EntryType::kNativeEntryData:
case ObjectPool::EntryType::kTaggedObject:
entry.raw_obj_ = d->ReadRef();
break;
@@ -2755,72 +2644,6 @@ class ContextScopeDeserializationCluster : public DeserializationCluster {
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class ParameterTypeCheckSerializationCluster : public SerializationCluster {
public:
ParameterTypeCheckSerializationCluster()
: SerializationCluster("ParameterTypeCheck") {}
~ParameterTypeCheckSerializationCluster() {}
void Trace(Serializer* s, ObjectPtr object) {
ParameterTypeCheckPtr unlinked = ParameterTypeCheck::RawCast(object);
objects_.Add(unlinked);
PushFromTo(unlinked);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kParameterTypeCheckCid);
const intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
ParameterTypeCheckPtr check = objects_[i];
s->AssignRef(check);
}
}
void WriteFill(Serializer* s) {
const intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
ParameterTypeCheckPtr check = objects_[i];
s->Write<intptr_t>(check->ptr()->index_);
WriteFromTo(check);
}
}
private:
GrowableArray<ParameterTypeCheckPtr> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
class ParameterTypeCheckDeserializationCluster : public DeserializationCluster {
public:
ParameterTypeCheckDeserializationCluster()
: DeserializationCluster("ParameterTypeCheck") {}
~ParameterTypeCheckDeserializationCluster() {}
void ReadAlloc(Deserializer* d, bool is_canonical) {
start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
const intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, ParameterTypeCheck::InstanceSize()));
}
stop_index_ = d->next_index();
}
void ReadFill(Deserializer* d, bool is_canonical) {
for (intptr_t id = start_index_; id < stop_index_; id++) {
ParameterTypeCheckPtr check =
static_cast<ParameterTypeCheckPtr>(d->Ref(id));
Deserializer::InitializeHeader(check, kParameterTypeCheckCid,
ParameterTypeCheck::InstanceSize());
check->ptr()->index_ = d->Read<intptr_t>();
ReadFromTo(check);
}
}
};
#if !defined(DART_PRECOMPILED_RUNTIME)
class UnlinkedCallSerializationCluster : public SerializationCluster {
public:
@@ -5024,22 +4847,6 @@ class VMSerializationRoots : public SerializationRoots {
"LocalVarDescriptors", "<empty>");
s->AddBaseObject(Object::empty_exception_handlers().raw(),
"ExceptionHandlers", "<empty>");
s->AddBaseObject(Object::implicit_getter_bytecode().raw(), "Bytecode",
"<implicit getter>");
s->AddBaseObject(Object::implicit_setter_bytecode().raw(), "Bytecode",
"<implicit setter>");
s->AddBaseObject(Object::implicit_static_getter_bytecode().raw(),
"Bytecode", "<implicit static getter>");
s->AddBaseObject(Object::method_extractor_bytecode().raw(), "Bytecode",
"<method extractor>");
s->AddBaseObject(Object::invoke_closure_bytecode().raw(), "Bytecode",
"<invoke closure>");
s->AddBaseObject(Object::invoke_field_bytecode().raw(), "Bytecode",
"<invoke field>");
s->AddBaseObject(Object::nsm_dispatcher_bytecode().raw(), "Bytecode",
"<nsm dispatcher>");
s->AddBaseObject(Object::dynamic_invocation_forwarder_bytecode().raw(),
"Bytecode", "<dyn forwarder>");
for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
s->AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i],
@@ -5121,14 +4928,6 @@ class VMDeserializationRoots : public DeserializationRoots {
d->AddBaseObject(Object::empty_descriptors().raw());
d->AddBaseObject(Object::empty_var_descriptors().raw());
d->AddBaseObject(Object::empty_exception_handlers().raw());
d->AddBaseObject(Object::implicit_getter_bytecode().raw());
d->AddBaseObject(Object::implicit_setter_bytecode().raw());
d->AddBaseObject(Object::implicit_static_getter_bytecode().raw());
d->AddBaseObject(Object::method_extractor_bytecode().raw());
d->AddBaseObject(Object::invoke_closure_bytecode().raw());
d->AddBaseObject(Object::invoke_field_bytecode().raw());
d->AddBaseObject(Object::nsm_dispatcher_bytecode().raw());
d->AddBaseObject(Object::dynamic_invocation_forwarder_bytecode().raw());
for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
d->AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
@@ -5754,8 +5553,6 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
return new (Z) KernelProgramInfoSerializationCluster();
case kCodeCid:
return new (Z) CodeSerializationCluster(heap_);
case kBytecodeCid:
return new (Z) BytecodeSerializationCluster();
case kObjectPoolCid:
return new (Z) ObjectPoolSerializationCluster();
case kPcDescriptorsCid:
@@ -5766,8 +5563,6 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
return new (Z) ContextSerializationCluster();
case kContextScopeCid:
return new (Z) ContextScopeSerializationCluster();
case kParameterTypeCheckCid:
return new (Z) ParameterTypeCheckSerializationCluster();
case kUnlinkedCallCid:
return new (Z) UnlinkedCallSerializationCluster();
case kICDataCid:
@@ -5934,12 +5729,6 @@ void Serializer::Push(ObjectPtr object) {
!Snapshot::IncludesCode(kind_)) {
return; // Do not trace, will write null.
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (object->IsHeapObject() && object->IsBytecode() &&
!Snapshot::IncludesBytecode(kind_)) {
return; // Do not trace, will write null.
}
#endif // !DART_PRECOMPILED_RUNTIME
intptr_t id = heap_->GetObjectId(object);
if (id == kUnreachableReference) {
@@ -6458,10 +6247,6 @@ DeserializationCluster* Deserializer::ReadCluster() {
#endif // !DART_PRECOMPILED_RUNTIME
case kCodeCid:
return new (Z) CodeDeserializationCluster();
#if !defined(DART_PRECOMPILED_RUNTIME)
case kBytecodeCid:
return new (Z) BytecodeDeserializationCluster();
#endif // !DART_PRECOMPILED_RUNTIME
case kObjectPoolCid:
return new (Z) ObjectPoolDeserializationCluster();
case kPcDescriptorsCid:
@@ -6472,8 +6257,6 @@ DeserializationCluster* Deserializer::ReadCluster() {
return new (Z) ContextDeserializationCluster();
case kContextScopeCid:
return new (Z) ContextScopeDeserializationCluster();
case kParameterTypeCheckCid:
return new (Z) ParameterTypeCheckDeserializationCluster();
case kUnlinkedCallCid:
return new (Z) UnlinkedCallDeserializationCluster();
case kICDataCid:
-5
View File
@@ -413,11 +413,6 @@ class Serializer : public ThreadStackResource {
if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
return RefId(Object::null());
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
return RefId(Object::null());
}
#endif // !DART_PRECOMPILED_RUNTIME
FATAL("Missing ref");
}
-12
View File
@@ -107,18 +107,6 @@ class CodePatcher : public AllStatic {
// Example pattern: `[0x3d, 0x8b, -1, -1]`.
bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size);
class KBCPatcher : public AllStatic {
public:
static NativeFunctionWrapper GetNativeCallAt(uword return_address,
const Bytecode& bytecode,
NativeFunction* function);
static void PatchNativeCallAt(uword return_address,
const Bytecode& bytecode,
NativeFunction function,
NativeFunctionWrapper trampoline);
};
} // namespace dart
#endif // RUNTIME_VM_CODE_PATCHER_H_
-38
View File
@@ -1,38 +0,0 @@
// Copyright (c) 2018, 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/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/code_patcher.h"
#include "vm/instructions_kbc.h"
#include "vm/native_entry.h"
namespace dart {
void KBCPatcher::PatchNativeCallAt(uword return_address,
const Bytecode& bytecode,
NativeFunction function,
NativeFunctionWrapper trampoline) {
ASSERT(bytecode.ContainsInstructionAt(return_address));
NativeEntryData native_entry_data(TypedData::Handle(
KBCNativeCallPattern::GetNativeEntryDataAt(return_address, bytecode)));
native_entry_data.set_trampoline(trampoline);
native_entry_data.set_native_function(function);
}
NativeFunctionWrapper KBCPatcher::GetNativeCallAt(uword return_address,
const Bytecode& bytecode,
NativeFunction* function) {
ASSERT(bytecode.ContainsInstructionAt(return_address));
NativeEntryData native_entry_data(TypedData::Handle(
KBCNativeCallPattern::GetNativeEntryDataAt(return_address, bytecode)));
*function = native_entry_data.native_function();
return native_entry_data.trampoline();
}
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+1 -10
View File
@@ -278,7 +278,7 @@ void Precompiler::DoCompileAll() {
if (FLAG_use_bare_instructions) {
// We use any stub here to get it's object pool (all stubs share the
// same object pool in bare instructions mode).
const Code& code = StubCode::InterpretCall();
const Code& code = StubCode::LazyCompile();
const ObjectPool& stub_pool = ObjectPool::Handle(code.object_pool());
global_object_pool_builder()->Reset();
@@ -420,7 +420,6 @@ void Precompiler::DoCompileAll() {
I->object_store()->set_async_star_move_next_helper(null_function);
I->object_store()->set_complete_on_async_return(null_function);
I->object_store()->set_async_star_stream_controller(null_class);
I->object_store()->set_bytecode_attributes(Array::null_array());
DropMetadata();
DropLibraryEntries();
}
@@ -1745,7 +1744,6 @@ void Precompiler::DropFunctions() {
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
function.DropUncompiledImplicitClosureFunction();
function.ClearBytecode();
if (functions_to_retain_.ContainsKey(function)) {
retained_functions.Add(function);
} else {
@@ -1795,7 +1793,6 @@ void Precompiler::DropFunctions() {
retained_functions = GrowableObjectArray::New();
for (intptr_t j = 0; j < closures.Length(); j++) {
function ^= closures.At(j);
function.ClearBytecode();
if (functions_to_retain_.ContainsKey(function)) {
retained_functions.Add(function);
} else {
@@ -1812,7 +1809,6 @@ void Precompiler::DropFields() {
Field& field = Field::Handle(Z);
GrowableObjectArray& retained_fields = GrowableObjectArray::Handle(Z);
AbstractType& type = AbstractType::Handle(Z);
Function& initializer_function = Function::Handle(Z);
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
for (intptr_t i = 0; i < libraries_.Length(); i++) {
@@ -1825,10 +1821,6 @@ void Precompiler::DropFields() {
for (intptr_t j = 0; j < fields.Length(); j++) {
field ^= fields.At(j);
bool retain = fields_to_retain_.HasKey(&field);
if (field.HasInitializerFunction()) {
initializer_function = field.InitializerFunction();
initializer_function.ClearBytecode();
}
#if !defined(PRODUCT)
if (field.is_instance() && cls.is_allocated()) {
// Keep instance fields so their names are available to graph tools.
@@ -2228,7 +2220,6 @@ void Precompiler::DropLibraryEntries() {
program_info.set_scripts(Array::null_array());
program_info.set_libraries_cache(Array::null_array());
program_info.set_classes_cache(Array::null_array());
program_info.set_bytecode_component(Array::null_array());
}
script.set_resolved_url(String::null_string());
script.set_compile_time_constants(Array::null_array());
+1 -1
View File
@@ -96,7 +96,7 @@ class FieldKeyValueTrait {
if (token_pos.IsReal()) {
return token_pos.value();
}
return key->binary_declaration_offset();
return key->kernel_offset();
}
static inline bool IsKeyEqual(Pair pair, Key key) {
@@ -639,7 +639,7 @@ void Assembler::TransitionNativeToGenerated(Register addr,
}
// Mark that the thread is executing Dart code.
LoadImmediate(state, target::Thread::vm_tag_compiled_id());
LoadImmediate(state, target::Thread::vm_tag_dart_id());
StoreToOffset(kWord, state, THR, target::Thread::vm_tag_offset());
LoadImmediate(state, target::Thread::generated_execution_state());
StoreToOffset(kWord, state, THR, target::Thread::execution_state_offset());
@@ -1483,7 +1483,7 @@ void Assembler::TransitionNativeToGenerated(Register state,
}
// Mark that the thread is executing Dart code.
LoadImmediate(state, target::Thread::vm_tag_compiled_id());
LoadImmediate(state, target::Thread::vm_tag_dart_id());
StoreToOffset(state, THR, target::Thread::vm_tag_offset());
LoadImmediate(state, target::Thread::generated_execution_state());
StoreToOffset(state, THR, target::Thread::execution_state_offset());
@@ -2288,8 +2288,7 @@ void Assembler::TransitionNativeToGenerated(Register scratch,
}
// Mark that the thread is executing Dart code.
movl(Assembler::VMTagAddress(),
Immediate(target::Thread::vm_tag_compiled_id()));
movl(Assembler::VMTagAddress(), Immediate(target::Thread::vm_tag_dart_id()));
movl(Address(THR, target::Thread::execution_state_offset()),
Immediate(target::Thread::generated_execution_state()));
@@ -245,8 +245,7 @@ void Assembler::TransitionNativeToGenerated(bool leave_safepoint) {
#endif
}
movq(Assembler::VMTagAddress(),
Immediate(target::Thread::vm_tag_compiled_id()));
movq(Assembler::VMTagAddress(), Immediate(target::Thread::vm_tag_dart_id()));
movq(Address(THR, target::Thread::execution_state_offset()),
Immediate(target::Thread::generated_execution_state()));
@@ -1,456 +0,0 @@
// Copyright (c) 2018, 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/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "platform/assert.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/constants_kbc.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
namespace dart {
static const char* kOpcodeNames[] = {
#define BYTECODE_NAME(name, encoding, kind, op1, op2, op3) #name,
KERNEL_BYTECODES_LIST(BYTECODE_NAME)
#undef BYTECODE_NAME
};
static const size_t kOpcodeCount =
sizeof(kOpcodeNames) / sizeof(kOpcodeNames[0]);
static_assert(kOpcodeCount <= 256, "Opcode should fit into a byte");
typedef void (*BytecodeFormatter)(char* buffer,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr);
typedef void (*Fmt)(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value);
template <typename ValueType>
void FormatOperand(char** buf,
intptr_t* size,
const char* fmt,
ValueType value) {
intptr_t written = Utils::SNPrint(*buf, *size, fmt, value);
if (written < *size) {
*buf += written;
*size += written;
} else {
*size = -1;
}
}
static void Fmt___(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {}
static void Fmttgt(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {
if (FLAG_disassemble_relative) {
FormatOperand(buf, size, "-> %" Pd, value);
} else {
FormatOperand(buf, size, "-> %" Px, instr + value);
}
}
static void Fmtlit(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {
FormatOperand(buf, size, "k%d", value);
}
static void Fmtreg(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {
FormatOperand(buf, size, "r%d", value);
}
static void Fmtxeg(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {
if (value < 0) {
FormatOperand(buf, size, "FP[%d]", value);
} else {
Fmtreg(buf, size, instr, value);
}
}
static void Fmtnum(char** buf,
intptr_t* size,
const KBCInstr* instr,
int32_t value) {
FormatOperand(buf, size, "#%d", value);
}
static void Apply(char** buf,
intptr_t* size,
const KBCInstr* instr,
Fmt fmt,
int32_t value,
const char* suffix) {
if (*size <= 0) {
return;
}
fmt(buf, size, instr, value);
if (*size > 0) {
FormatOperand(buf, size, "%s", suffix);
}
}
static void Format0(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {}
static void FormatA(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t a = KernelBytecode::DecodeA(instr);
Apply(&buf, &size, instr, op1, a, "");
}
static void FormatD(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t bc = KernelBytecode::DecodeD(instr);
Apply(&buf, &size, instr, op1, bc, "");
}
static void FormatX(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t bc = KernelBytecode::DecodeX(instr);
Apply(&buf, &size, instr, op1, bc, "");
}
static void FormatT(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t x = KernelBytecode::DecodeT(instr);
Apply(&buf, &size, instr, op1, x, "");
}
static void FormatA_E(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t a = KernelBytecode::DecodeA(instr);
const int32_t e = KernelBytecode::DecodeE(instr);
Apply(&buf, &size, instr, op1, a, ", ");
Apply(&buf, &size, instr, op2, e, "");
}
static void FormatA_Y(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t a = KernelBytecode::DecodeA(instr);
const int32_t y = KernelBytecode::DecodeY(instr);
Apply(&buf, &size, instr, op1, a, ", ");
Apply(&buf, &size, instr, op2, y, "");
}
static void FormatD_F(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t d = KernelBytecode::DecodeD(instr);
const int32_t f = KernelBytecode::DecodeF(instr);
Apply(&buf, &size, instr, op1, d, ", ");
Apply(&buf, &size, instr, op2, f, "");
}
static void FormatA_B_C(char* buf,
intptr_t size,
KernelBytecode::Opcode opcode,
const KBCInstr* instr,
Fmt op1,
Fmt op2,
Fmt op3) {
const int32_t a = KernelBytecode::DecodeA(instr);
const int32_t b = KernelBytecode::DecodeB(instr);
const int32_t c = KernelBytecode::DecodeC(instr);
Apply(&buf, &size, instr, op1, a, ", ");
Apply(&buf, &size, instr, op2, b, ", ");
Apply(&buf, &size, instr, op3, c, "");
}
#define BYTECODE_FORMATTER(name, encoding, kind, op1, op2, op3) \
static void Format##name(char* buf, intptr_t size, \
KernelBytecode::Opcode opcode, \
const KBCInstr* instr) { \
Format##encoding(buf, size, opcode, instr, Fmt##op1, Fmt##op2, Fmt##op3); \
}
KERNEL_BYTECODES_LIST(BYTECODE_FORMATTER)
#undef BYTECODE_FORMATTER
static const BytecodeFormatter kFormatters[] = {
#define BYTECODE_FORMATTER(name, encoding, kind, op1, op2, op3) &Format##name,
KERNEL_BYTECODES_LIST(BYTECODE_FORMATTER)
#undef BYTECODE_FORMATTER
};
static intptr_t GetConstantPoolIndex(const KBCInstr* instr) {
switch (KernelBytecode::DecodeOpcode(instr)) {
case KernelBytecode::kLoadConstant:
case KernelBytecode::kLoadConstant_Wide:
case KernelBytecode::kInstantiateTypeArgumentsTOS:
case KernelBytecode::kInstantiateTypeArgumentsTOS_Wide:
case KernelBytecode::kAssertAssignable:
case KernelBytecode::kAssertAssignable_Wide:
return KernelBytecode::DecodeE(instr);
case KernelBytecode::kPushConstant:
case KernelBytecode::kPushConstant_Wide:
case KernelBytecode::kInitLateField:
case KernelBytecode::kInitLateField_Wide:
case KernelBytecode::kStoreStaticTOS:
case KernelBytecode::kStoreStaticTOS_Wide:
case KernelBytecode::kLoadStatic:
case KernelBytecode::kLoadStatic_Wide:
case KernelBytecode::kAllocate:
case KernelBytecode::kAllocate_Wide:
case KernelBytecode::kAllocateClosure:
case KernelBytecode::kAllocateClosure_Wide:
case KernelBytecode::kInstantiateType:
case KernelBytecode::kInstantiateType_Wide:
case KernelBytecode::kDirectCall:
case KernelBytecode::kDirectCall_Wide:
case KernelBytecode::kUncheckedDirectCall:
case KernelBytecode::kUncheckedDirectCall_Wide:
case KernelBytecode::kInterfaceCall:
case KernelBytecode::kInterfaceCall_Wide:
case KernelBytecode::kInstantiatedInterfaceCall:
case KernelBytecode::kInstantiatedInterfaceCall_Wide:
case KernelBytecode::kUncheckedClosureCall:
case KernelBytecode::kUncheckedClosureCall_Wide:
case KernelBytecode::kUncheckedInterfaceCall:
case KernelBytecode::kUncheckedInterfaceCall_Wide:
case KernelBytecode::kDynamicCall:
case KernelBytecode::kDynamicCall_Wide:
return KernelBytecode::DecodeD(instr);
default:
return -1;
}
}
static bool GetLoadedObjectAt(uword pc,
const ObjectPool& object_pool,
Object* obj) {
const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
const intptr_t index = GetConstantPoolIndex(instr);
if (index >= 0) {
if (object_pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
*obj = object_pool.ObjectAt(index);
return true;
}
}
return false;
}
void KernelBytecodeDisassembler::DecodeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
int* out_instr_size,
const Bytecode& bytecode,
Object** object,
uword pc) {
const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
const intptr_t instr_size = KernelBytecode::kInstructionSize[opcode];
size_t name_size =
Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
human_buffer += name_size;
human_size -= name_size;
kFormatters[opcode](human_buffer, human_size, opcode, instr);
const intptr_t kCharactersPerByte = 3;
if (hex_size > instr_size * kCharactersPerByte) {
for (intptr_t i = 0; i < instr_size; ++i) {
Utils::SNPrint(hex_buffer + (i * kCharactersPerByte),
hex_size - (i * kCharactersPerByte), " %02x", instr[i]);
}
}
if (out_instr_size != nullptr) {
*out_instr_size = instr_size;
}
*object = NULL;
if (!bytecode.IsNull()) {
*object = &Object::Handle();
const ObjectPool& pool = ObjectPool::Handle(bytecode.object_pool());
if (!GetLoadedObjectAt(pc, pool, *object)) {
*object = NULL;
}
}
}
void KernelBytecodeDisassembler::Disassemble(uword start,
uword end,
DisassemblyFormatter* formatter,
const Bytecode& bytecode) {
#if !defined(PRODUCT)
ASSERT(formatter != NULL);
char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
uword pc = start;
GrowableArray<const Function*> inlined_functions;
GrowableArray<TokenPosition> token_positions;
while (pc < end) {
int instruction_length;
Object* object;
DecodeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
sizeof(human_buffer), &instruction_length, bytecode,
&object, pc);
formatter->ConsumeInstruction(hex_buffer, sizeof(hex_buffer), human_buffer,
sizeof(human_buffer), object,
FLAG_disassemble_relative ? pc - start : pc);
pc += instruction_length;
}
#else
UNREACHABLE();
#endif
}
void KernelBytecodeDisassembler::Disassemble(const Function& function) {
#if !defined(PRODUCT)
ASSERT(function.HasBytecode());
const char* function_fullname = function.ToFullyQualifiedCString();
Zone* zone = Thread::Current()->zone();
const Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
THR_Print("Bytecode for function '%s' {\n", function_fullname);
const uword start = bytecode.PayloadStart();
const uword base = FLAG_disassemble_relative ? 0 : start;
DisassembleToStdout stdout_formatter;
LogBlock lb;
Disassemble(start, start + bytecode.Size(), &stdout_formatter, bytecode);
THR_Print("}\n");
const ObjectPool& object_pool =
ObjectPool::Handle(zone, bytecode.object_pool());
object_pool.DebugPrint();
THR_Print("PC Descriptors for function '%s' {\n", function_fullname);
PcDescriptors::PrintHeaderString();
const PcDescriptors& descriptors =
PcDescriptors::Handle(zone, bytecode.pc_descriptors());
THR_Print("%s}\n", descriptors.ToCString());
if (bytecode.HasSourcePositions()) {
THR_Print("Source positions for function '%s' {\n", function_fullname);
// 4 bits per hex digit + 2 for "0x".
const int addr_width = (kBitsPerWord / 4) + 2;
// "*" in a printf format specifier tells it to read the field width from
// the printf argument list.
THR_Print("%-*s\tpos\tline\tcolumn\tyield\n", addr_width, "pc");
const Script& script = Script::Handle(zone, function.script());
kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
while (iter.MoveNext()) {
TokenPosition pos = iter.TokenPos();
intptr_t line = -1, column = -1;
script.GetTokenLocation(pos, &line, &column);
THR_Print("%#-*" Px "\t%s\t%" Pd "\t%" Pd "\t%s\n", addr_width,
base + iter.PcOffset(), pos.ToCString(), line, column,
iter.IsYieldPoint() ? "yield" : "");
}
THR_Print("}\n");
}
if (FLAG_print_variable_descriptors && bytecode.HasLocalVariablesInfo()) {
THR_Print("Local variables info for function '%s' {\n", function_fullname);
kernel::BytecodeLocalVariablesIterator iter(zone, bytecode);
while (iter.MoveNext()) {
switch (iter.Kind()) {
case kernel::BytecodeLocalVariablesIterator::kScope: {
THR_Print("scope 0x%" Px "-0x%" Px " pos %s-%s\tlev %" Pd "\n",
base + iter.StartPC(), base + iter.EndPC(),
iter.StartTokenPos().ToCString(),
iter.EndTokenPos().ToCString(), iter.ContextLevel());
} break;
case kernel::BytecodeLocalVariablesIterator::kVariableDeclaration: {
THR_Print("var 0x%" Px "-0x%" Px " pos %s-%s\tidx %" Pd
"\tdecl %s\t%s %s %s\n",
base + iter.StartPC(), base + iter.EndPC(),
iter.StartTokenPos().ToCString(),
iter.EndTokenPos().ToCString(), iter.Index(),
iter.DeclarationTokenPos().ToCString(),
String::Handle(
zone, AbstractType::Handle(zone, iter.Type()).Name())
.ToCString(),
String::Handle(zone, iter.Name()).ToCString(),
iter.IsCaptured() ? "captured" : "");
} break;
case kernel::BytecodeLocalVariablesIterator::kContextVariable: {
THR_Print("ctxt 0x%" Px "\tidx %" Pd "\n", base + iter.StartPC(),
iter.Index());
} break;
}
}
THR_Print("}\n");
THR_Print("Local variable descriptors for function '%s' {\n",
function_fullname);
const auto& var_descriptors =
LocalVarDescriptors::Handle(zone, bytecode.GetLocalVarDescriptors());
THR_Print("%s}\n", var_descriptors.ToCString());
}
THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
const ExceptionHandlers& handlers =
ExceptionHandlers::Handle(zone, bytecode.exception_handlers());
THR_Print("%s}\n", handlers.ToCString());
#else
UNREACHABLE();
#endif
}
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -1,89 +0,0 @@
// Copyright (c) 2018, 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_COMPILER_ASSEMBLER_DISASSEMBLER_KBC_H_
#define RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_KBC_H_
#include "vm/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/assembler/disassembler.h"
namespace dart {
// Disassemble instructions.
class KernelBytecodeDisassembler : public AllStatic {
public:
// Disassemble instructions between start and end.
// (The assumption is that start is at a valid instruction).
// Return true if all instructions were successfully decoded, false otherwise.
static void Disassemble(uword start,
uword end,
DisassemblyFormatter* formatter,
const Bytecode& bytecode);
static void Disassemble(uword start,
uword end,
DisassemblyFormatter* formatter) {
Disassemble(start, end, formatter, Bytecode::Handle());
}
static void Disassemble(uword start, uword end, const Bytecode& bytecode) {
#if !defined(PRODUCT)
DisassembleToStdout stdout_formatter;
LogBlock lb;
Disassemble(start, end, &stdout_formatter, bytecode);
#else
UNREACHABLE();
#endif
}
static void Disassemble(uword start, uword end) {
#if !defined(PRODUCT)
DisassembleToStdout stdout_formatter;
LogBlock lb;
Disassemble(start, end, &stdout_formatter);
#else
UNREACHABLE();
#endif
}
static void Disassemble(uword start,
uword end,
char* buffer,
uintptr_t buffer_size) {
#if !defined(PRODUCT)
DisassembleToMemory memory_formatter(buffer, buffer_size);
LogBlock lb;
Disassemble(start, end, &memory_formatter);
#else
UNREACHABLE();
#endif
}
// Decodes one instruction.
// Writes a hexadecimal representation into the hex_buffer and a
// human-readable representation into the human_buffer.
// Writes the length of the decoded instruction in bytes in out_instr_len.
static void DecodeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
int* out_instr_len,
const Bytecode& bytecode,
Object** object,
uword pc);
static void Disassemble(const Function& function);
private:
static const int kHexadecimalBufferSize = 32;
static const int kUserReadableBufferSize = 256;
};
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_COMPILER_ASSEMBLER_DISASSEMBLER_KBC_H_
@@ -30,7 +30,6 @@ struct ObjectPoolBuilderEntry {
kImmediate,
kNativeFunction,
kNativeFunctionWrapper,
kNativeEntryData,
};
using TypeBits = BitField<uint8_t, EntryType, 0, 7>;
-4
View File
@@ -162,10 +162,6 @@ class FlowGraph : public ZoneAllocated {
}
intptr_t CurrentContextEnvIndex() const {
if (function().HasBytecode()) {
return -1;
}
return EnvIndex(parsed_function().current_context_var());
}
+3 -6
View File
@@ -775,8 +775,7 @@ static intptr_t Usage(const Function& function) {
// 'function' is queued for optimized compilation
count = FLAG_optimization_counter_threshold;
} else {
// 'function' is queued for unoptimized compilation
count = FLAG_compilation_counter_threshold;
count = 0;
}
} else if (Code::IsOptimized(function.CurrentCode())) {
// 'function' was optimized and stopped counting
@@ -4834,10 +4833,8 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UpdateReceiverSminess(zone);
if ((compiler->is_optimizing() || compiler->function().HasBytecode()) &&
HasICData()) {
ASSERT(HasICData());
if (compiler->is_optimizing() && (ic_data()->NumberOfUsedChecks() > 0)) {
if (compiler->is_optimizing() && HasICData()) {
if (ic_data()->NumberOfUsedChecks() > 0) {
const ICData& unary_ic_data =
ICData::ZoneHandle(zone, ic_data()->AsUnaryClassChecks());
compiler->GenerateInstanceCall(deopt_id(), token_pos(), locs(),
+8 -23
View File
@@ -174,29 +174,14 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
// which enables us to remove more stores.
std::vector<const char*> expected_stores_jit;
std::vector<const char*> expected_stores_aot;
if (root_library.is_declared_in_bytecode()) {
// Bytecode flow graph builder doesn't provide readable
// variable names for captured variables. Also, bytecode may omit
// stores of context parent in certain cases.
expected_stores_jit.insert(
expected_stores_jit.end(),
{":context_var0", "Context.parent", ":context_var0",
"Closure.function_type_arguments", "Closure.function",
"Closure.context"});
expected_stores_aot.insert(
expected_stores_aot.end(),
{":context_var0", "Closure.function_type_arguments", "Closure.function",
"Closure.context"});
} else {
// These expectations are for AST-based flow graph builder.
expected_stores_jit.insert(expected_stores_jit.end(),
{"value", "Context.parent", "Context.parent",
"value", "Closure.function_type_arguments",
"Closure.function", "Closure.context"});
expected_stores_aot.insert(expected_stores_aot.end(),
{"value", "Closure.function_type_arguments",
"Closure.function", "Closure.context"});
}
expected_stores_jit.insert(expected_stores_jit.end(),
{"value", "Context.parent", "Context.parent",
"value", "Closure.function_type_arguments",
"Closure.function", "Closure.context"});
expected_stores_aot.insert(expected_stores_aot.end(),
{"value", "Closure.function_type_arguments",
"Closure.function", "Closure.context"});
RunInitializingStoresTest(root_library, "f4", CompilerPass::kJIT,
expected_stores_jit);
@@ -71,12 +71,6 @@ TypeParameterPtr GetFunctionTypeParameter(const Function& fun,
}
ObjectPtr Invoke(const Library& lib, const char* name) {
// These tests rely on running unoptimized code to collect type feedback. The
// interpreter does not collect type feedback for interface calls, so set
// compilation threshold to 0 in order to compile invoked function
// immediately and execute compiled code.
SetFlagScope<int> sfs(&FLAG_compilation_counter_threshold, 0);
Thread* thread = Thread::Current();
Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
Dart_Handle result;
+30 -62
View File
@@ -216,74 +216,42 @@ ISOLATE_UNIT_TEST_CASE(Inliner_List_generate) {
ILMatcher cursor(flow_graph, entry, /*trace=*/true,
ParallelMovesHandling::kSkip);
if (function.is_declared_in_bytecode()) {
RELEASE_ASSERT(cursor.TryMatch({
kMoveGlob,
kMatchAndMoveCreateArray,
kWordSize == 8 ? kMatchAndMoveUnboxInt64 : kNop,
kMatchAndMoveGoto,
Instruction* unbox1 = nullptr;
Instruction* unbox2 = nullptr;
// Loop header
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveUnboxInt64,
kMatchAndMoveBranchTrue,
RELEASE_ASSERT(cursor.TryMatch({
kMoveGlob,
kMatchAndMoveCreateArray,
kMatchAndMoveUnboxInt64,
{kMoveAny, &unbox1},
{kMoveAny, &unbox2},
kMatchAndMoveGoto,
// Loop body
kMatchAndMoveTargetEntry,
kMatchAndMoveGenericCheckBound,
kMatchAndMoveStoreIndexed,
kMatchAndMoveCheckedSmiOp,
kMatchAndMoveGoto,
// Loop header
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveBranchTrue,
// Loop header once again
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveUnboxInt64,
kMatchAndMoveBranchFalse,
// Loop body
kMatchAndMoveTargetEntry,
kWordSize == 4 ? kMatchAndMoveBoxInt64 : kNop,
kMatchAndMoveBoxInt64,
kMatchAndMoveStoreIndexed,
kMatchAndMoveBinaryInt64Op,
kMatchAndMoveGoto,
// After loop
kMatchAndMoveTargetEntry,
kMatchReturn,
}));
} else {
Instruction* unbox1 = nullptr;
Instruction* unbox2 = nullptr;
// Loop header once again
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveBranchFalse,
RELEASE_ASSERT(cursor.TryMatch({
kMoveGlob,
kMatchAndMoveCreateArray,
kMatchAndMoveUnboxInt64,
{kMoveAny, &unbox1},
{kMoveAny, &unbox2},
kMatchAndMoveGoto,
// After loop
kMatchAndMoveTargetEntry,
kMatchReturn,
}));
// Loop header
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveBranchTrue,
// Loop body
kMatchAndMoveTargetEntry,
kWordSize == 4 ? kMatchAndMoveBoxInt64 : kNop,
kMatchAndMoveBoxInt64,
kMatchAndMoveStoreIndexed,
kMatchAndMoveBinaryInt64Op,
kMatchAndMoveGoto,
// Loop header once again
kMatchAndMoveJoinEntry,
kMatchAndMoveCheckStackOverflow,
kMatchAndMoveBranchFalse,
// After loop
kMatchAndMoveTargetEntry,
kMatchReturn,
}));
EXPECT(unbox1->IsUnboxedConstant() || unbox1->IsUnboxInt64());
EXPECT(unbox2->IsUnboxedConstant() || unbox2->IsUnboxInt64());
}
EXPECT(unbox1->IsUnboxedConstant() || unbox1->IsUnboxInt64());
EXPECT(unbox2->IsUnboxedConstant() || unbox2->IsUnboxInt64());
}
#endif // defined(DART_PRECOMPILER)
@@ -13,7 +13,6 @@
#include "vm/compiler/backend/loops.h"
#include "vm/compiler/backend/type_propagator.h"
#include "vm/compiler/compiler_pass.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/kernel_to_il.h"
#include "vm/compiler/jit/jit_call_specializer.h"
#include "vm/flags.h"
@@ -60,35 +59,6 @@ static void FlattenScopeIntoEnvironment(FlowGraph* graph,
}
}
#if !defined(PRODUCT)
void PopulateEnvironmentFromBytecodeLocalVariables(
const Function& function,
FlowGraph* graph,
GrowableArray<LocalVariable*>* env) {
const auto& bytecode = Bytecode::Handle(function.bytecode());
ASSERT(!bytecode.IsNull());
kernel::BytecodeLocalVariablesIterator iter(Thread::Current()->zone(),
bytecode);
while (iter.MoveNext()) {
if (iter.IsVariableDeclaration() && !iter.IsCaptured()) {
LocalVariable* const var = new LocalVariable(
TokenPosition::kNoSource, TokenPosition::kNoSource,
String::ZoneHandle(graph->zone(), iter.Name()),
AbstractType::ZoneHandle(graph->zone(), iter.Type()));
if (iter.Index() < 0) { // Parameter.
var->set_index(VariableIndex(-iter.Index() - kKBCParamEndSlotFromFp));
} else {
var->set_index(VariableIndex(-iter.Index()));
}
const intptr_t env_index = graph->EnvIndex(var);
env->EnsureLength(env_index + 1, nullptr);
(*env)[env_index] = var;
}
}
}
#endif
// Run TryCatchAnalyzer optimization on the function foo from the given script
// and check that the only variables from the given list are synchronized
// on catch entry.
@@ -118,17 +88,7 @@ static void TryCatchOptimizerTest(
auto scope = graph->parsed_function().scope();
GrowableArray<LocalVariable*> env;
if (function.is_declared_in_bytecode()) {
#if defined(PRODUCT)
// In product mode information about local variables is not retained in
// bytecode, so we can't find variables by names.
return;
#else
PopulateEnvironmentFromBytecodeLocalVariables(function, graph, &env);
#endif
} else {
FlattenScopeIntoEnvironment(graph, scope, &env);
}
FlattenScopeIntoEnvironment(graph, scope, &env);
for (intptr_t i = 0; i < env.length(); i++) {
bool found = false;
-10
View File
@@ -111,14 +111,6 @@ compiler_sources = [
"ffi/recognized_method.h",
"frontend/base_flow_graph_builder.cc",
"frontend/base_flow_graph_builder.h",
"frontend/bytecode_fingerprints.cc",
"frontend/bytecode_fingerprints.h",
"frontend/bytecode_flow_graph_builder.cc",
"frontend/bytecode_flow_graph_builder.h",
"frontend/bytecode_reader.cc",
"frontend/bytecode_reader.h",
"frontend/bytecode_scope_builder.cc",
"frontend/bytecode_scope_builder.h",
"frontend/constant_reader.cc",
"frontend/constant_reader.h",
"frontend/flow_graph_builder.cc",
@@ -210,7 +202,5 @@ disassembler_sources = [
"assembler/disassembler.h",
"assembler/disassembler_arm.cc",
"assembler/disassembler_arm64.cc",
"assembler/disassembler_kbc.cc",
"assembler/disassembler_kbc.h",
"assembler/disassembler_x86.cc",
]
+1 -19
View File
@@ -69,15 +69,6 @@ class CompilerState : public ThreadStackResource {
// Create a dummy list of local variables representing a context object
// with the given number of captured variables and given ID.
//
// Used during bytecode to IL translation because AllocateContext and
// CloneContext IL instructions need a list of local varaibles and bytecode
// does not record this information.
//
// TODO(vegorov): create context classes for distinct context IDs and
// populate them with slots without creating variables.
// Beware that context_id is satured at 8-bits, so multiple contexts may
// share id 255.
const ZoneGrowableArray<const Slot*>& GetDummyContextSlots(
intptr_t context_id,
intptr_t num_context_slots);
@@ -85,16 +76,8 @@ class CompilerState : public ThreadStackResource {
// Create a dummy LocalVariable that represents a captured local variable
// at the given index in the context with given ID.
//
// Used during bytecode to IL translation because StoreInstanceField and
// LoadField IL instructions need Slot, which can only be created from a
// LocalVariable.
//
// This function returns the same variable when it is called with the
// same index.
//
// TODO(vegorov): disambiguate slots for different context IDs.
// Beware that context_id is saturated at 8-bits, so multiple contexts may
// share id 255.
LocalVariable* GetDummyCapturedVariable(intptr_t context_id, intptr_t index);
bool is_aot() const { return is_aot_; }
@@ -115,8 +98,7 @@ class CompilerState : public ThreadStackResource {
// Cache for Slot objects created during compilation (see slot.h).
SlotCache* slot_cache_ = nullptr;
// Caches for dummy LocalVariables and context Slots created during bytecode
// to IL translation.
// Caches for dummy LocalVariables and context Slots.
ZoneGrowableArray<ZoneGrowableArray<const Slot*>*>* dummy_slots_ = nullptr;
ZoneGrowableArray<LocalVariable*>* dummy_captured_vars_ = nullptr;
@@ -465,7 +465,6 @@ class BaseFlowGraphBuilder {
const Array& saved_args_desc_array_;
friend class StreamingFlowGraphBuilder;
friend class BytecodeFlowGraphBuilder;
private:
DISALLOW_COPY_AND_ASSIGN(BaseFlowGraphBuilder);
@@ -1,207 +0,0 @@
// Copyright (c) 2019, 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/compiler/frontend/bytecode_fingerprints.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/constants_kbc.h"
#include "vm/hash.h"
namespace dart {
namespace kernel {
static uint32_t CombineObject(uint32_t hash, const Object& obj) {
if (obj.IsAbstractType()) {
return CombineHashes(hash, AbstractType::Cast(obj).Hash());
} else if (obj.IsClass()) {
return CombineHashes(hash, Class::Cast(obj).id());
} else if (obj.IsFunction()) {
return CombineHashes(
hash, AbstractType::Handle(Function::Cast(obj).result_type()).Hash());
} else if (obj.IsField()) {
return CombineHashes(hash,
AbstractType::Handle(Field::Cast(obj).type()).Hash());
} else {
return CombineHashes(hash, static_cast<uint32_t>(obj.GetClassId()));
}
}
typedef uint32_t (*Fp)(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value);
static uint32_t Fp___(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return fp;
}
static uint32_t Fptgt(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fplit(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineObject(fp, Object::Handle(pool.ObjectAt(value)));
}
static uint32_t Fpreg(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fpxeg(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fpnum(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
int32_t value) {
return CombineHashes(fp, value);
}
static uint32_t Fingerprint0(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
return fp;
}
static uint32_t FingerprintA(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
return fp;
}
static uint32_t FingerprintD(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
return fp;
}
static uint32_t FingerprintX(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeX(instr));
return fp;
}
static uint32_t FingerprintT(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeT(instr));
return fp;
}
static uint32_t FingerprintA_E(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeE(instr));
return fp;
}
static uint32_t FingerprintA_Y(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeY(instr));
return fp;
}
static uint32_t FingerprintD_F(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeD(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeF(instr));
return fp;
}
static uint32_t FingerprintA_B_C(uint32_t fp,
const KBCInstr* instr,
const ObjectPool& pool,
Fp op1,
Fp op2,
Fp op3) {
fp = op1(fp, instr, pool, KernelBytecode::DecodeA(instr));
fp = op2(fp, instr, pool, KernelBytecode::DecodeB(instr));
fp = op3(fp, instr, pool, KernelBytecode::DecodeC(instr));
return fp;
}
uint32_t BytecodeFingerprintHelper::CalculateFunctionFingerprint(
const Function& function) {
ASSERT(function.is_declared_in_bytecode());
const intptr_t kHashBits = 30;
uint32_t fp = 0;
fp = CombineHashes(fp, String::Handle(function.UserVisibleName()).Hash());
if (function.is_abstract()) {
return FinalizeHash(fp, kHashBits);
}
if (!function.HasBytecode()) {
kernel::BytecodeReader::ReadFunctionBytecode(Thread::Current(), function);
}
const Bytecode& code = Bytecode::Handle(function.bytecode());
const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
const KBCInstr* const start =
reinterpret_cast<const KBCInstr*>(code.instructions());
for (const KBCInstr* instr = start; (instr - start) < code.Size();
instr = KernelBytecode::Next(instr)) {
const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
fp = CombineHashes(fp, opcode);
switch (opcode) {
#define FINGERPRINT_BYTECODE(name, encoding, kind, op1, op2, op3) \
case KernelBytecode::k##name: \
fp = Fingerprint##encoding(fp, instr, pool, Fp##op1, Fp##op2, Fp##op3); \
break;
KERNEL_BYTECODES_LIST(FINGERPRINT_BYTECODE)
#undef FINGERPRINT_BYTECODE
default:
UNREACHABLE();
}
}
return FinalizeHash(fp, kHashBits);
}
} // namespace kernel
} // namespace dart
@@ -1,26 +0,0 @@
// Copyright (c) 2019, 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_COMPILER_FRONTEND_BYTECODE_FINGERPRINTS_H_
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FINGERPRINTS_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "platform/allocation.h"
#include "vm/object.h"
namespace dart {
namespace kernel {
class BytecodeFingerprintHelper : public AllStatic {
public:
static uint32_t CalculateFunctionFingerprint(const Function& func);
};
} // namespace kernel
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FINGERPRINTS_H_
File diff suppressed because it is too large Load Diff
@@ -1,252 +0,0 @@
// Copyright (c) 2018, 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_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/backend/il.h"
#include "vm/compiler/frontend/base_flow_graph_builder.h"
#include "vm/compiler/frontend/kernel_translation_helper.h" // For InferredTypeMetadata
#include "vm/constants_kbc.h"
namespace dart {
namespace kernel {
class BytecodeLocalVariablesIterator;
// This class builds flow graph from bytecode. It is used either to compile
// from bytecode, or generate bytecode interpreter (the latter is not
// fully implemented yet).
// TODO(alexmarkov): extend this class and IL to generate an interpreter in
// addition to compiling bytecode.
class BytecodeFlowGraphBuilder {
public:
BytecodeFlowGraphBuilder(BaseFlowGraphBuilder* flow_graph_builder,
ParsedFunction* parsed_function,
ZoneGrowableArray<const ICData*>* ic_data_array)
: flow_graph_builder_(flow_graph_builder),
zone_(flow_graph_builder->zone_),
is_generating_interpreter_(
false), // TODO(alexmarkov): pass as argument
parsed_function_(parsed_function),
ic_data_array_(ic_data_array),
object_pool_(ObjectPool::Handle(zone_)),
bytecode_length_(0),
pc_(0),
position_(TokenPosition::kNoSource),
local_vars_(zone_, 0),
parameters_(zone_, 0),
exception_var_(nullptr),
stacktrace_var_(nullptr),
scratch_var_(nullptr),
prologue_info_(-1, -1),
throw_no_such_method_(nullptr),
inferred_types_attribute_(Array::Handle(zone_)) {}
FlowGraph* BuildGraph();
// Create parameter variables without building a flow graph.
void CreateParameterVariables();
protected:
// Returns `true` if building a flow graph for a bytecode interpreter, or
// `false` if compiling a function from bytecode.
bool is_generating_interpreter() const { return is_generating_interpreter_; }
private:
// Operand of bytecode instruction, either intptr_t value (if compiling
// bytecode) or Definition (if generating interpreter).
class Operand {
public:
explicit Operand(Definition* definition)
: definition_(definition), value_(0) {
ASSERT(definition != nullptr);
}
explicit Operand(intptr_t value) : definition_(nullptr), value_(value) {}
Definition* definition() const {
ASSERT(definition_ != nullptr);
return definition_;
}
intptr_t value() const {
ASSERT(definition_ == nullptr);
return value_;
}
private:
Definition* definition_;
intptr_t value_;
};
// Constant from a constant pool.
// It is either Object (if compiling bytecode) or Definition
// (if generating interpreter).
class Constant {
public:
explicit Constant(Definition* definition)
: definition_(definition), value_(Object::null_object()) {
ASSERT(definition != nullptr);
}
explicit Constant(Zone* zone, const Object& value)
: definition_(nullptr), value_(value) {}
Definition* definition() const {
ASSERT(definition_ != nullptr);
return definition_;
}
const Object& value() const {
ASSERT(definition_ == nullptr);
return value_;
}
private:
Definition* definition_;
const Object& value_;
};
// Scope declared in bytecode local variables information.
class BytecodeScope : public ZoneAllocated {
public:
BytecodeScope(Zone* zone,
intptr_t end_pc,
intptr_t context_level,
BytecodeScope* parent)
: end_pc_(end_pc),
context_level_(context_level),
parent_(parent),
hidden_vars_(zone, 4) {}
const intptr_t end_pc_;
const intptr_t context_level_;
BytecodeScope* const parent_;
ZoneGrowableArray<LocalVariable*> hidden_vars_;
};
Operand DecodeOperandA();
Operand DecodeOperandB();
Operand DecodeOperandC();
Operand DecodeOperandD();
Operand DecodeOperandE();
Operand DecodeOperandF();
Operand DecodeOperandX();
Operand DecodeOperandY();
Operand DecodeOperandT();
Constant ConstantAt(Operand entry_index, intptr_t add_index = 0);
void PushConstant(Constant constant);
Constant PopConstant();
void LoadStackSlots(intptr_t num_slots);
void AllocateLocalVariables(Operand frame_size,
intptr_t num_param_locals = 0);
LocalVariable* AllocateParameter(intptr_t param_index,
VariableIndex var_index);
void AllocateFixedParameters();
// Allocates parameters and local variables in case of EntryOptional.
// Returns pointer to the instruction after EntryOptional/LoadConstant/Frame
// bytecodes.
const KBCInstr* AllocateParametersAndLocalsForEntryOptional();
LocalVariable* LocalVariableAt(intptr_t local_index);
void StoreLocal(Operand local_index);
void LoadLocal(Operand local_index);
Value* Pop();
intptr_t GetStackDepth() const;
bool IsStackEmpty() const;
InferredTypeMetadata GetInferredType(intptr_t pc);
void PropagateStackState(intptr_t target_pc);
void DropUnusedValuesFromStack();
void BuildJumpIfStrictCompare(Token::Kind cmp_kind);
void BuildPrimitiveOp(const String& name,
Token::Kind token_kind,
const AbstractType& static_receiver_type,
int num_args);
void BuildIntOp(const String& name, Token::Kind token_kind, int num_args);
void BuildDoubleOp(const String& name, Token::Kind token_kind, int num_args);
void BuildDirectCallCommon(bool is_unchecked_call);
void BuildInterfaceCallCommon(bool is_unchecked_call,
bool is_instantiated_call);
void BuildInstruction(KernelBytecode::Opcode opcode);
void BuildFfiAsFunction();
void BuildFfiNativeCallbackFunction();
void BuildDebugStepCheck();
#define DECLARE_BUILD_METHOD(name, encoding, kind, op1, op2, op3) \
void Build##name();
KERNEL_BYTECODES_LIST(DECLARE_BUILD_METHOD)
#undef DECLARE_BUILD_METHOD
intptr_t GetTryIndex(const PcDescriptors& descriptors, intptr_t pc);
JoinEntryInstr* EnsureControlFlowJoin(const PcDescriptors& descriptors,
intptr_t pc);
bool RequiresScratchVar(const KBCInstr* instr);
void CollectControlFlow(const PcDescriptors& descriptors,
const ExceptionHandlers& handlers,
GraphEntryInstr* graph_entry);
// Update current scope, context level and local variables for the given PC.
// Returns next PC where scope might need an update.
intptr_t UpdateScope(BytecodeLocalVariablesIterator* iter, intptr_t pc);
// Figure out entry points style.
UncheckedEntryPointStyle ChooseEntryPointStyle(
const KBCInstr* jump_if_unchecked);
Thread* thread() const { return flow_graph_builder_->thread_; }
Isolate* isolate() const { return thread()->isolate(); }
ParsedFunction* parsed_function() const {
ASSERT(!is_generating_interpreter());
return parsed_function_;
}
const Function& function() const { return parsed_function()->function(); }
BaseFlowGraphBuilder* flow_graph_builder_;
Zone* zone_;
bool is_generating_interpreter_;
// The following members are available only when compiling bytecode.
ParsedFunction* parsed_function_;
ZoneGrowableArray<const ICData*>* ic_data_array_;
ObjectPool& object_pool_;
const KBCInstr* raw_bytecode_ = nullptr;
intptr_t bytecode_length_;
intptr_t pc_;
intptr_t next_pc_ = -1;
const KBCInstr* bytecode_instr_ = nullptr;
TokenPosition position_;
intptr_t last_yield_point_pc_ = 0;
intptr_t last_yield_point_index_ = 0;
Fragment code_;
ZoneGrowableArray<LocalVariable*> local_vars_;
ZoneGrowableArray<LocalVariable*> parameters_;
LocalVariable* exception_var_;
LocalVariable* stacktrace_var_;
LocalVariable* scratch_var_;
IntMap<JoinEntryInstr*> jump_targets_;
IntMap<Value*> stack_states_;
PrologueInfo prologue_info_;
JoinEntryInstr* throw_no_such_method_;
GraphEntryInstr* graph_entry_ = nullptr;
UncheckedEntryPointStyle entry_point_style_ = UncheckedEntryPointStyle::kNone;
bool build_debug_step_checks_ = false;
bool seen_parameters_scope_ = false;
BytecodeScope* current_scope_ = nullptr;
Array& inferred_types_attribute_;
intptr_t inferred_types_index_ = 0;
};
} // namespace kernel
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_FLOW_GRAPH_BUILDER_H_
File diff suppressed because it is too large Load Diff
@@ -1,589 +0,0 @@
// Copyright (c) 2018, 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_COMPILER_FRONTEND_BYTECODE_READER_H_
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/constants_kbc.h"
#include "vm/object.h"
namespace dart {
namespace kernel {
class BytecodeComponentData;
// Helper class which provides access to bytecode metadata.
class BytecodeMetadataHelper : public MetadataHelper {
public:
static const char* tag() { return "vm.bytecode"; }
explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
ActiveClass* active_class);
void ParseBytecodeFunction(ParsedFunction* parsed_function);
// Read all library declarations.
bool ReadLibraries();
// Read specific library declaration.
void ReadLibrary(const Library& library);
// Scan through libraries in the bytecode component and figure out if any of
// them will replace libraries which are already loaded.
// Return true if bytecode component is found.
bool FindModifiedLibrariesForHotReload(BitVector* modified_libs,
bool* is_empty_program,
intptr_t* p_num_classes,
intptr_t* p_num_procedures);
LibraryPtr GetMainLibrary();
ArrayPtr GetBytecodeComponent();
ArrayPtr ReadBytecodeComponent();
private:
ActiveClass* const active_class_;
DISALLOW_COPY_AND_ASSIGN(BytecodeMetadataHelper);
};
// Helper class for reading bytecode.
class BytecodeReaderHelper : public ValueObject {
public:
explicit BytecodeReaderHelper(TranslationHelper* translation_helper,
ActiveClass* active_class,
BytecodeComponentData* bytecode_component);
Reader& reader() { return reader_; }
void ReadCode(const Function& function, intptr_t code_offset);
ArrayPtr CreateForwarderChecks(const Function& function);
void ReadMembers(const Class& cls, bool discard_fields);
void ReadFieldDeclarations(const Class& cls, bool discard_fields);
void ReadFunctionDeclarations(const Class& cls);
void ReadClassDeclaration(const Class& cls);
void ReadLibraryDeclaration(const Library& library, bool lookup_classes);
void ReadLibraryDeclarations(intptr_t num_libraries);
void FindAndReadSpecificLibrary(const Library& library,
intptr_t num_libraries);
void FindModifiedLibrariesForHotReload(BitVector* modified_libs,
intptr_t num_libraries);
void ParseBytecodeFunction(ParsedFunction* parsed_function,
const Function& function);
LibraryPtr ReadMain();
ArrayPtr ReadBytecodeComponent(intptr_t md_offset);
void ResetObjects();
// Fills in [is_covariant] and [is_generic_covariant_impl] vectors
// according to covariance attributes of [function] parameters.
//
// [function] should be declared in bytecode.
// [is_covariant] and [is_generic_covariant_impl] should contain bitvectors
// of function.NumParameters() length.
void ReadParameterCovariance(const Function& function,
BitVector* is_covariant,
BitVector* is_generic_covariant_impl);
// Returns an flattened array of tuples {isFinal, defaultValue, metadata},
// or an Error.
ObjectPtr BuildParameterDescriptor(const Function& function);
// Read bytecode PackedObject.
ObjectPtr ReadObject();
private:
// These constants should match corresponding constants in class ObjectHandle
// (pkg/vm/lib/bytecode/object_table.dart).
static const int kReferenceBit = 1 << 0;
static const int kIndexShift = 1;
static const int kKindShift = 1;
static const int kKindMask = 0x0f;
static const int kFlagBit0 = 1 << 5;
static const int kFlagBit1 = 1 << 6;
static const int kFlagBit2 = 1 << 7;
static const int kFlagBit3 = 1 << 8;
static const int kFlagBit4 = 1 << 9;
static const int kFlagBit5 = 1 << 10;
static const int kTagMask = (kFlagBit0 | kFlagBit1 | kFlagBit2 | kFlagBit3);
static const int kNullabilityMask = (kFlagBit4 | kFlagBit5);
static const int kFlagsMask = (kTagMask | kNullabilityMask);
// Code flags, must be in sync with Code constants in
// pkg/vm/lib/bytecode/declarations.dart.
struct Code {
static const int kHasExceptionsTableFlag = 1 << 0;
static const int kHasSourcePositionsFlag = 1 << 1;
static const int kHasNullableFieldsFlag = 1 << 2;
static const int kHasClosuresFlag = 1 << 3;
static const int kHasParameterFlagsFlag = 1 << 4;
static const int kHasForwardingStubTargetFlag = 1 << 5;
static const int kHasDefaultFunctionTypeArgsFlag = 1 << 6;
static const int kHasLocalVariablesFlag = 1 << 7;
};
// Closure code flags, must be in sync with ClosureCode constants in
// pkg/vm/lib/bytecode/declarations.dart.
struct ClosureCode {
static const int kHasExceptionsTableFlag = 1 << 0;
static const int kHasSourcePositionsFlag = 1 << 1;
static const int kHasLocalVariablesFlag = 1 << 2;
};
// Parameter flags, must be in sync with ParameterDeclaration constants in
// pkg/vm/lib/bytecode/declarations.dart.
struct Parameter {
static const int kIsCovariantFlag = 1 << 0;
static const int kIsGenericCovariantImplFlag = 1 << 1;
static const int kIsFinalFlag = 1 << 2;
static const int kIsRequiredFlag = 1 << 3;
};
class FunctionTypeScope : public ValueObject {
public:
explicit FunctionTypeScope(BytecodeReaderHelper* bytecode_reader)
: bytecode_reader_(bytecode_reader),
saved_type_parameters_(
bytecode_reader->function_type_type_parameters_) {}
~FunctionTypeScope() {
bytecode_reader_->function_type_type_parameters_ = saved_type_parameters_;
}
private:
BytecodeReaderHelper* bytecode_reader_;
const TypeArguments* const saved_type_parameters_;
};
class FunctionScope : public ValueObject {
public:
FunctionScope(BytecodeReaderHelper* bytecode_reader,
const Function& function,
const String& name,
const Class& cls)
: bytecode_reader_(bytecode_reader) {
ASSERT(bytecode_reader_->scoped_function_.IsNull());
ASSERT(bytecode_reader_->scoped_function_name_.IsNull());
ASSERT(bytecode_reader_->scoped_function_class_.IsNull());
ASSERT(name.IsSymbol());
bytecode_reader_->scoped_function_ = function.raw();
bytecode_reader_->scoped_function_name_ = name.raw();
bytecode_reader_->scoped_function_class_ = cls.raw();
}
~FunctionScope() {
bytecode_reader_->scoped_function_ = Function::null();
bytecode_reader_->scoped_function_name_ = String::null();
bytecode_reader_->scoped_function_class_ = Class::null();
}
private:
BytecodeReaderHelper* bytecode_reader_;
};
void ReadClosureDeclaration(const Function& function, intptr_t closureIndex);
TypePtr ReadFunctionSignature(const Function& func,
bool has_optional_positional_params,
bool has_optional_named_params,
bool has_type_params,
bool has_positional_param_names,
bool has_parameter_flags,
Nullability nullability);
void ReadTypeParametersDeclaration(const Class& parameterized_class,
const Function& parameterized_function);
// Read portion of constant pool corresponding to one function/closure.
// Start with [start_index], and stop when reaching EndClosureFunctionScope.
// Return index of the last read constant pool entry.
intptr_t ReadConstantPool(const Function& function,
const ObjectPool& pool,
intptr_t start_index);
BytecodePtr ReadBytecode(const ObjectPool& pool);
void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
void ReadLocalVariables(const Bytecode& bytecode, bool has_local_variables);
TypedDataPtr NativeEntry(const Function& function,
const String& external_name);
StringPtr ConstructorName(const Class& cls, const String& name);
ObjectPtr ReadObjectContents(uint32_t header);
ObjectPtr ReadConstObject(intptr_t tag);
ObjectPtr ReadType(intptr_t tag, Nullability nullability);
StringPtr ReadString(bool is_canonical = true);
ScriptPtr ReadSourceFile(const String& uri, intptr_t offset);
TypeArgumentsPtr ReadTypeArguments();
void ReadAttributes(const Object& key);
PatchClassPtr GetPatchClass(const Class& cls, const Script& script);
void ParseForwarderFunction(ParsedFunction* parsed_function,
const Function& function,
const Function& target);
bool IsExpressionEvaluationLibrary(const Library& library) const {
return expression_evaluation_library_ != nullptr &&
expression_evaluation_library_->raw() == library.raw();
}
// Similar to cls.EnsureClassDeclaration, but may be more efficient if
// class is from the current kernel binary.
void LoadReferencedClass(const Class& cls);
Reader reader_;
TranslationHelper& translation_helper_;
ActiveClass* const active_class_;
Thread* const thread_;
Zone* const zone_;
BytecodeComponentData* bytecode_component_;
Array* closures_ = nullptr;
const TypeArguments* function_type_type_parameters_ = nullptr;
GrowableObjectArray* pending_recursive_types_ = nullptr;
PatchClass* patch_class_ = nullptr;
Array* functions_ = nullptr;
intptr_t function_index_ = 0;
Function& scoped_function_;
String& scoped_function_name_;
Class& scoped_function_class_;
Library* expression_evaluation_library_ = nullptr;
bool loading_native_wrappers_library_ = false;
bool reading_type_arguments_of_recursive_type_ = false;
DISALLOW_COPY_AND_ASSIGN(BytecodeReaderHelper);
};
class BytecodeComponentData : ValueObject {
public:
enum {
kVersion,
kStringsHeaderOffset,
kStringsContentsOffset,
kObjectOffsetsOffset,
kNumObjects,
kObjectsContentsOffset,
kMainOffset,
kNumLibraries,
kLibraryIndexOffset,
kLibrariesOffset,
kNumClasses,
kClassesOffset,
kMembersOffset,
kNumCodes,
kCodesOffset,
kSourcePositionsOffset,
kSourceFilesOffset,
kLineStartsOffset,
kLocalVariablesOffset,
kAnnotationsOffset,
kNumFields
};
explicit BytecodeComponentData(Array* data) : data_(*data) {}
void Init(const Array& data) { data_ = data.raw(); }
intptr_t GetVersion() const;
intptr_t GetStringsHeaderOffset() const;
intptr_t GetStringsContentsOffset() const;
intptr_t GetObjectOffsetsOffset() const;
intptr_t GetNumObjects() const;
intptr_t GetObjectsContentsOffset() const;
intptr_t GetMainOffset() const;
intptr_t GetNumLibraries() const;
intptr_t GetLibraryIndexOffset() const;
intptr_t GetLibrariesOffset() const;
intptr_t GetNumClasses() const;
intptr_t GetClassesOffset() const;
intptr_t GetMembersOffset() const;
intptr_t GetNumCodes() const;
intptr_t GetCodesOffset() const;
intptr_t GetSourcePositionsOffset() const;
intptr_t GetSourceFilesOffset() const;
intptr_t GetLineStartsOffset() const;
intptr_t GetLocalVariablesOffset() const;
intptr_t GetAnnotationsOffset() const;
void SetObject(intptr_t index, const Object& obj) const;
ObjectPtr GetObject(intptr_t index) const;
bool IsNull() const { return data_.IsNull(); }
static ArrayPtr New(Zone* zone,
intptr_t version,
intptr_t num_objects,
intptr_t strings_header_offset,
intptr_t strings_contents_offset,
intptr_t object_offsets_offset,
intptr_t objects_contents_offset,
intptr_t main_offset,
intptr_t num_libraries,
intptr_t library_index_offset,
intptr_t libraries_offset,
intptr_t num_classes,
intptr_t classes_offset,
intptr_t members_offset,
intptr_t num_codes,
intptr_t codes_offset,
intptr_t source_positions_offset,
intptr_t source_files_offset,
intptr_t line_starts_offset,
intptr_t local_variables_offset,
intptr_t annotations_offset,
Heap::Space space);
private:
Array& data_;
};
class BytecodeReader : public AllStatic {
public:
// Reads bytecode for the given function and sets its bytecode field.
// Returns error (if any), or null.
static ErrorPtr ReadFunctionBytecode(Thread* thread,
const Function& function);
// Read annotations for the given annotation field.
static ObjectPtr ReadAnnotation(const Field& annotation_field);
// Read the |count| annotations following given annotation field.
static ArrayPtr ReadExtendedAnnotations(const Field& annotation_field,
intptr_t count);
static void ResetObjectTable(const KernelProgramInfo& info);
// Read declaration of the given library.
static void LoadLibraryDeclaration(const Library& library);
// Read declaration of the given class.
static void LoadClassDeclaration(const Class& cls);
// Read members of the given class.
static void FinishClassLoading(const Class& cls);
// Value of attribute [name] of Function/Field [key].
static ObjectPtr GetBytecodeAttribute(const Object& key, const String& name);
#if !defined(PRODUCT)
// Compute local variable descriptors for [function] with [bytecode].
static LocalVarDescriptorsPtr ComputeLocalVarDescriptors(
Zone* zone,
const Function& function,
const Bytecode& bytecode);
#endif
};
class InferredTypeBytecodeAttribute : public AllStatic {
public:
// Number of array elements per entry in InferredType bytecode
// attribute (PC, type, flags).
static constexpr intptr_t kNumElements = 3;
// Field type is the first entry with PC = -1.
static constexpr intptr_t kFieldTypePC = -1;
// Returns PC at given index.
static intptr_t GetPCAt(const Array& attr, intptr_t index) {
return Smi::Value(Smi::RawCast(attr.At(index)));
}
// Returns InferredType metadata at given index.
static InferredTypeMetadata GetInferredTypeAt(Zone* zone,
const Array& attr,
intptr_t index);
};
class BytecodeSourcePositionsIterator : ValueObject {
public:
// These constants should match corresponding constants in class
// SourcePositions (pkg/vm/lib/bytecode/source_positions.dart).
static const intptr_t kSyntheticCodeMarker = -1;
static const intptr_t kYieldPointMarker = -2;
BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
: reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))) {
if (bytecode.HasSourcePositions()) {
reader_.set_offset(bytecode.source_positions_binary_offset());
pairs_remaining_ = reader_.ReadUInt();
}
}
bool MoveNext() {
if (pairs_remaining_ == 0) {
return false;
}
ASSERT(pairs_remaining_ > 0);
--pairs_remaining_;
cur_bci_ += reader_.ReadUInt();
cur_token_pos_ += reader_.ReadSLEB128();
is_yield_point_ = false;
if (cur_token_pos_ == kYieldPointMarker) {
const bool result = MoveNext();
is_yield_point_ = true;
return result;
}
return true;
}
uword PcOffset() const { return cur_bci_; }
TokenPosition TokenPos() const {
return (cur_token_pos_ == kSyntheticCodeMarker)
? TokenPosition::kNoSource
: TokenPosition(cur_token_pos_);
}
bool IsYieldPoint() const { return is_yield_point_; }
private:
Reader reader_;
intptr_t pairs_remaining_ = 0;
intptr_t cur_bci_ = 0;
intptr_t cur_token_pos_ = 0;
bool is_yield_point_ = false;
};
class BytecodeLocalVariablesIterator : ValueObject {
public:
// These constants should match corresponding constants in
// pkg/vm/lib/bytecode/local_variable_table.dart.
enum {
kInvalid,
kScope,
kVariableDeclaration,
kContextVariable,
};
static const intptr_t kKindMask = 0xF;
static const intptr_t kIsCapturedFlag = 1 << 4;
BytecodeLocalVariablesIterator(Zone* zone, const Bytecode& bytecode)
: reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
object_pool_(ObjectPool::Handle(zone, bytecode.object_pool())) {
if (bytecode.HasLocalVariablesInfo()) {
reader_.set_offset(bytecode.local_variables_binary_offset());
entries_remaining_ = reader_.ReadUInt();
}
}
bool MoveNext() {
if (entries_remaining_ <= 0) {
// Finished looking at the last entry, now we're done.
entries_remaining_ = -1;
return false;
}
--entries_remaining_;
cur_kind_and_flags_ = reader_.ReadByte();
cur_start_pc_ += reader_.ReadSLEB128();
switch (Kind()) {
case kScope:
cur_end_pc_ = cur_start_pc_ + reader_.ReadUInt();
cur_index_ = reader_.ReadSLEB128();
cur_token_pos_ = reader_.ReadPosition();
cur_end_token_pos_ = reader_.ReadPosition();
break;
case kVariableDeclaration:
cur_index_ = reader_.ReadSLEB128();
cur_name_ = reader_.ReadUInt();
cur_type_ = reader_.ReadUInt();
cur_declaration_token_pos_ = reader_.ReadPosition();
cur_token_pos_ = reader_.ReadPosition();
break;
case kContextVariable:
cur_index_ = reader_.ReadSLEB128();
break;
}
return true;
}
// Returns true after iterator moved past the last entry and
// MoveNext() returned false.
bool IsDone() const { return entries_remaining_ < 0; }
intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
bool IsScope() const { return Kind() == kScope; }
bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
bool IsContextVariable() const { return Kind() == kContextVariable; }
intptr_t StartPC() const { return cur_start_pc_; }
intptr_t EndPC() const {
ASSERT(IsScope() || IsVariableDeclaration());
return cur_end_pc_;
}
intptr_t ContextLevel() const {
ASSERT(IsScope());
return cur_index_;
}
TokenPosition StartTokenPos() const {
ASSERT(IsScope() || IsVariableDeclaration());
return cur_token_pos_;
}
TokenPosition EndTokenPos() const {
ASSERT(IsScope() || IsVariableDeclaration());
return cur_end_token_pos_;
}
intptr_t Index() const {
ASSERT(IsVariableDeclaration() || IsContextVariable());
return cur_index_;
}
StringPtr Name() const {
ASSERT(IsVariableDeclaration());
return String::RawCast(object_pool_.ObjectAt(cur_name_));
}
AbstractTypePtr Type() const {
ASSERT(IsVariableDeclaration());
return AbstractType::RawCast(object_pool_.ObjectAt(cur_type_));
}
TokenPosition DeclarationTokenPos() const {
ASSERT(IsVariableDeclaration());
return cur_declaration_token_pos_;
}
bool IsCaptured() const {
ASSERT(IsVariableDeclaration());
return (cur_kind_and_flags_ & kIsCapturedFlag) != 0;
}
private:
Reader reader_;
const ObjectPool& object_pool_;
intptr_t entries_remaining_ = 0;
intptr_t cur_kind_and_flags_ = 0;
intptr_t cur_start_pc_ = 0;
intptr_t cur_end_pc_ = 0;
intptr_t cur_index_ = -1;
intptr_t cur_name_ = -1;
intptr_t cur_type_ = -1;
TokenPosition cur_token_pos_ = TokenPosition::kNoSource;
TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource;
TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource;
};
class BytecodeAttributesMapTraits {
public:
static const char* Name() { return "BytecodeAttributesMapTraits"; }
static bool ReportStats() { return false; }
static bool IsMatch(const Object& a, const Object& b) {
return a.raw() == b.raw();
}
static uword Hash(const Object& key) {
return String::HashRawSymbol(key.IsFunction() ? Function::Cast(key).name()
: Field::Cast(key).name());
}
};
typedef UnorderedHashMap<BytecodeAttributesMapTraits> BytecodeAttributesMap;
bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
Zone* zone);
} // namespace kernel
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
@@ -1,194 +0,0 @@
// Copyright (c) 2018, 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/compiler/frontend/bytecode_scope_builder.h"
#include "vm/compiler/frontend/bytecode_reader.h"
namespace dart {
namespace kernel {
#define Z (zone_)
BytecodeScopeBuilder::BytecodeScopeBuilder(ParsedFunction* parsed_function)
: parsed_function_(parsed_function),
zone_(parsed_function->zone()),
scope_(nullptr) {}
void BytecodeScopeBuilder::BuildScopes() {
if (parsed_function_->scope() != nullptr) {
return; // Scopes are already built.
}
const Function& function = parsed_function_->function();
LocalScope* enclosing_scope = nullptr;
if (function.IsImplicitClosureFunction() && !function.is_static()) {
// Create artificial enclosing scope for the tear-off that contains
// captured receiver value. This ensure that AssertAssignable will correctly
// load instantiator type arguments if they are needed.
LocalVariable* receiver_variable =
MakeReceiverVariable(/* is_parameter = */ false);
receiver_variable->set_is_captured();
enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
enclosing_scope->set_context_level(0);
enclosing_scope->AddVariable(receiver_variable);
enclosing_scope->AddContextVariable(receiver_variable);
}
scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
scope_->set_begin_token_pos(function.token_pos());
scope_->set_end_token_pos(function.end_token_pos());
// Add function type arguments variable before current context variable.
if ((function.IsGeneric() || function.HasGenericParent())) {
LocalVariable* type_args_var = MakeVariable(
Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
scope_->AddVariable(type_args_var);
parsed_function_->set_function_type_arguments(type_args_var);
}
bool needs_expr_temp = false;
if (parsed_function_->has_arg_desc_var()) {
needs_expr_temp = true;
scope_->AddVariable(parsed_function_->arg_desc_var());
}
LocalVariable* context_var = parsed_function_->current_context_var();
context_var->set_is_forced_stack();
scope_->AddVariable(context_var);
parsed_function_->set_scope(scope_);
switch (function.kind()) {
case FunctionLayout::kImplicitClosureFunction: {
ASSERT(function.NumImplicitParameters() == 1);
const auto& parent = Function::Handle(Z, function.parent_function());
const auto& target =
Function::Handle(Z, function.ImplicitClosureTarget(Z));
// For BuildGraphOfNoSuchMethodForwarder, since closures no longer
// require arg_desc_var in all cases.
if (target.IsNull() ||
(parent.num_fixed_parameters() != target.num_fixed_parameters())) {
needs_expr_temp = true;
}
LocalVariable* closure_parameter = MakeVariable(
Symbols::ClosureParameter(), AbstractType::dynamic_type());
closure_parameter->set_is_forced_stack();
scope_->InsertParameterAt(0, closure_parameter);
// Type check all parameters by default.
// This may be overridden with parameter flags in
// BytecodeReaderHelper::ParseForwarderFunction.
AddParameters(function, LocalVariable::kDoTypeCheck);
break;
}
case FunctionLayout::kImplicitGetter:
case FunctionLayout::kImplicitSetter: {
const bool is_setter = function.IsImplicitSetterFunction();
const bool is_method = !function.IsStaticFunction();
const Field& field = Field::Handle(Z, function.accessor_field());
intptr_t pos = 0;
if (is_method) {
MakeReceiverVariable(/* is_parameter = */ true);
++pos;
}
if (is_setter) {
LocalVariable* setter_value = MakeVariable(
Symbols::Value(),
AbstractType::ZoneHandle(Z, function.ParameterTypeAt(pos)));
scope_->InsertParameterAt(pos++, setter_value);
if (is_method) {
if (field.is_covariant()) {
setter_value->set_is_explicit_covariant_parameter();
} else {
const bool needs_type_check =
field.is_generic_covariant_impl() &&
kernel::ProcedureAttributesOf(field, Z).has_non_this_uses;
if (!needs_type_check) {
setter_value->set_type_check_mode(
LocalVariable::kTypeCheckedByCaller);
}
}
}
}
break;
}
case FunctionLayout::kImplicitStaticGetter: {
ASSERT(!IsStaticFieldGetterGeneratedAsInitializer(function, Z));
break;
}
case FunctionLayout::kDynamicInvocationForwarder: {
// Create [this] variable.
MakeReceiverVariable(/* is_parameter = */ true);
// Type check all parameters by default.
// This may be overridden with parameter flags in
// BytecodeReaderHelper::ParseForwarderFunction.
AddParameters(function, LocalVariable::kDoTypeCheck);
break;
}
case FunctionLayout::kMethodExtractor: {
// Add a receiver parameter. Though it is captured, we emit code to
// explicitly copy it to a fixed offset in a freshly-allocated context
// instead of using the generic code for regular functions.
// Therefore, it isn't necessary to mark it as captured here.
MakeReceiverVariable(/* is_parameter = */ true);
break;
}
default:
UNREACHABLE();
}
if (needs_expr_temp) {
scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
}
if (parsed_function_->function().MayHaveUncheckedEntryPoint()) {
scope_->AddVariable(parsed_function_->EnsureEntryPointsTemp());
}
parsed_function_->AllocateVariables();
}
// TODO(alexmarkov): pass bitvectors of parameter covariance to set type
// check mode before AllocateVariables.
void BytecodeScopeBuilder::AddParameters(const Function& function,
LocalVariable::TypeCheckMode mode) {
for (intptr_t i = function.NumImplicitParameters(),
n = function.NumParameters();
i < n; ++i) {
// LocalVariable caches handles, so new handles are created for each
// parameter.
String& name = String::ZoneHandle(Z, function.ParameterNameAt(i));
AbstractType& type =
AbstractType::ZoneHandle(Z, function.ParameterTypeAt(i));
LocalVariable* variable = MakeVariable(name, type);
variable->set_type_check_mode(mode);
scope_->InsertParameterAt(i, variable);
}
}
LocalVariable* BytecodeScopeBuilder::MakeVariable(const String& name,
const AbstractType& type) {
return new (Z) LocalVariable(TokenPosition::kNoSource,
TokenPosition::kNoSource, name, type, nullptr);
}
LocalVariable* BytecodeScopeBuilder::MakeReceiverVariable(bool is_parameter) {
const auto& cls = Class::Handle(Z, parsed_function_->function().Owner());
const auto& type = Type::ZoneHandle(Z, cls.DeclarationType());
LocalVariable* receiver_variable = MakeVariable(Symbols::This(), type);
parsed_function_->set_receiver_var(receiver_variable);
if (is_parameter) {
scope_->InsertParameterAt(0, receiver_variable);
}
return receiver_variable;
}
} // namespace kernel
} // namespace dart
@@ -1,41 +0,0 @@
// Copyright (c) 2019, 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_COMPILER_FRONTEND_BYTECODE_SCOPE_BUILDER_H_
#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_SCOPE_BUILDER_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/object.h"
#include "vm/parser.h" // For ParsedFunction.
#include "vm/scopes.h"
namespace dart {
namespace kernel {
// Builds scopes, populates parameters and local variables for
// certain functions declared in bytecode.
class BytecodeScopeBuilder : public ValueObject {
public:
explicit BytecodeScopeBuilder(ParsedFunction* parsed_function);
void BuildScopes();
private:
void AddParameters(const Function& function,
LocalVariable::TypeCheckMode mode);
LocalVariable* MakeVariable(const String& name, const AbstractType& type);
LocalVariable* MakeReceiverVariable(bool is_parameter);
ParsedFunction* parsed_function_;
Zone* zone_;
LocalScope* scope_;
};
} // namespace kernel
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_SCOPE_BUILDER_H_
@@ -212,7 +212,7 @@ InstancePtr ConstantReader::ReadConstantInternal(intptr_t constant_offset) {
case kInstanceConstant: {
const NameIndex index = reader.ReadCanonicalNameReference();
const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
if (!klass.is_declaration_loaded() && !klass.is_declared_in_bytecode()) {
if (!klass.is_declaration_loaded()) {
FATAL1(
"Trying to evaluate an instance constant whose references class "
"%s is not loaded yet.",
@@ -5,8 +5,6 @@
#include "vm/compiler/frontend/kernel_binary_flowgraph.h"
#include "vm/compiler/ffi/callback.h"
#include "vm/compiler/frontend/bytecode_flow_graph_builder.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/flow_graph_builder.h" // For dart::FlowGraphBuilder::SimpleInstanceOfType.
#include "vm/compiler/frontend/prologue_builder.h"
#include "vm/compiler/jit/compiler.h"
@@ -15,9 +13,6 @@
#include "vm/stack_frame.h"
namespace dart {
DECLARE_FLAG(bool, enable_interpreter);
namespace kernel {
#define Z (zone_)
@@ -1055,55 +1050,6 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraph() {
ActiveMemberScope active_member(active_class(), &outermost_function);
ActiveTypeParametersScope active_type_params(active_class(), function, Z);
if (function.is_declared_in_bytecode()) {
bytecode_metadata_helper_.ParseBytecodeFunction(parsed_function());
switch (function.kind()) {
case FunctionLayout::kImplicitClosureFunction:
return B->BuildGraphOfImplicitClosureFunction(function);
case FunctionLayout::kImplicitGetter:
case FunctionLayout::kImplicitSetter:
return B->BuildGraphOfFieldAccessor(function);
case FunctionLayout::kImplicitStaticGetter: {
if (IsStaticFieldGetterGeneratedAsInitializer(function, Z)) {
break;
}
return B->BuildGraphOfFieldAccessor(function);
}
case FunctionLayout::kDynamicInvocationForwarder:
return B->BuildGraphOfDynamicInvocationForwarder(function);
case FunctionLayout::kMethodExtractor:
return B->BuildGraphOfMethodExtractor(function);
case FunctionLayout::kNoSuchMethodDispatcher:
return B->BuildGraphOfNoSuchMethodDispatcher(function);
default:
break;
}
ASSERT(function.HasBytecode());
BytecodeFlowGraphBuilder bytecode_compiler(
flow_graph_builder_, parsed_function(),
&(flow_graph_builder_->ic_data_array_));
if (B->IsRecognizedMethodForFlowGraph(function)) {
bytecode_compiler.CreateParameterVariables();
return B->BuildGraphOfRecognizedMethod(function);
}
return bytecode_compiler.BuildGraph();
}
// Certain special functions could have a VM-internal bytecode
// attached to them.
ASSERT((!function.HasBytecode()) ||
(function.kind() == FunctionLayout::kImplicitGetter) ||
(function.kind() == FunctionLayout::kImplicitSetter) ||
(function.kind() == FunctionLayout::kImplicitStaticGetter) ||
(function.kind() == FunctionLayout::kMethodExtractor) ||
(function.kind() == FunctionLayout::kInvokeFieldDispatcher) ||
(function.kind() == FunctionLayout::kNoSuchMethodDispatcher));
ParseKernelASTFunction();
switch (function.kind()) {
@@ -3174,8 +3120,6 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
NULL));
// Special case identical(x, y) call.
// Note: similar optimization is performed in bytecode flow graph builder -
// see BytecodeFlowGraphBuilder::BuildDirectCall().
// TODO(27590) consider moving this into the inliner and force inline it
// there.
if (special_case_identical) {
@@ -9,7 +9,6 @@
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_to_il.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
@@ -41,7 +40,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
&constant_reader_,
active_class_,
/* finalize= */ true),
bytecode_metadata_helper_(this, active_class_),
direct_call_metadata_helper_(this),
inferred_type_metadata_helper_(this, &constant_reader_),
procedure_attributes_metadata_helper_(this),
@@ -413,7 +411,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
ActiveClass* const active_class_;
ConstantReader constant_reader_;
TypeTranslator type_translator_;
BytecodeMetadataHelper bytecode_metadata_helper_;
DirectCallMetadataHelper direct_call_metadata_helper_;
InferredTypeMetadataHelper inferred_type_metadata_helper_;
ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
+2 -13
View File
@@ -743,15 +743,9 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
info.potential_natives() == GrowableObjectArray::null());
#endif
auto& kernel_data = ExternalTypedData::Handle(Z);
intptr_t kernel_data_program_offset = 0;
if (!function.is_declared_in_bytecode()) {
kernel_data = function.KernelData();
kernel_data_program_offset = function.KernelDataProgramOffset();
}
auto& kernel_data = ExternalTypedData::Handle(Z, function.KernelData());
intptr_t kernel_data_program_offset = function.KernelDataProgramOffset();
// TODO(alexmarkov): refactor this - StreamingFlowGraphBuilder should not be
// used for bytecode functions.
StreamingFlowGraphBuilder streaming_flow_graph_builder(
this, kernel_data, kernel_data_program_offset);
return streaming_flow_graph_builder.BuildGraph();
@@ -837,11 +831,6 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph(
case MethodRecognizer::kFfiStorePointer:
case MethodRecognizer::kFfiFromAddress:
case MethodRecognizer::kFfiGetAddress:
// This list must be kept in sync with BytecodeReaderHelper::NativeEntry in
// runtime/vm/compiler/frontend/bytecode_reader.cc and implemented in the
// bytecode interpreter in runtime/vm/interpreter.cc. Alternatively, these
// methods must work in their original form (a Dart body or native entry) in
// the bytecode interpreter.
case MethodRecognizer::kObjectEquals:
case MethodRecognizer::kStringBaseLength:
case MethodRecognizer::kStringBaseIsEmpty:
@@ -578,9 +578,6 @@ ClassPtr TranslationHelper::LookupClassByKernelClass(NameIndex kernel_class) {
Class::Handle(Z, library.LookupClassAllowPrivate(class_name));
CheckStaticLookup(klass);
ASSERT(!klass.IsNull());
if (klass.is_declared_in_bytecode()) {
klass.EnsureDeclarationLoaded();
}
name_index_handle_ = Smi::New(kernel_class);
return info_.InsertClass(thread_, name_index_handle_, klass);
}
@@ -2982,9 +2979,6 @@ void TypeTranslator::BuildInterfaceType(bool simple) {
const Class& klass = Class::Handle(Z, H.LookupClassByKernelClass(klass_name));
ASSERT(!klass.IsNull());
if (klass.is_declared_in_bytecode()) {
klass.EnsureDeclarationLoaded();
}
if (simple) {
if (finalize_ || klass.is_type_finalized()) {
// Fast path for non-generic types: retrieve or populate the class's only
@@ -194,11 +194,6 @@ class TranslationHelper {
const char* format,
...) PRINTF_ATTRIBUTE(5, 6);
ArrayPtr GetBytecodeComponent() const { return info_.bytecode_component(); }
void SetBytecodeComponent(const Array& bytecode_component) {
info_.set_bytecode_component(bytecode_component);
}
void SetExpressionEvaluationFunction(const Function& function) {
ASSERT(expression_evaluation_function_ == nullptr);
expression_evaluation_function_ = &Function::Handle(zone_, function.raw());
@@ -1260,8 +1255,6 @@ class KernelReaderHelper {
// kernel program.
intptr_t data_program_offset_;
friend class BytecodeMetadataHelper;
friend class BytecodeReaderHelper;
friend class ClassHelper;
friend class CallSiteAttributesMetadataHelper;
friend class ConstantReader;
@@ -20,7 +20,7 @@ namespace kernel {
bool MethodCanSkipTypeChecksForNonCovariantTypeArguments(
const Function& method) {
// Dart 2 type system at non-dynamic call sites statically guarantees that
// argument values match declarated parameter types for all non-covariant
// argument values match declared parameter types for all non-covariant
// and non-generic-covariant parameters. The same applies to type parameters
// bounds for type parameters of generic functions.
//
@@ -29,12 +29,7 @@ bool MethodCanSkipTypeChecksForNonCovariantTypeArguments(
//
// Though for some kinds of methods (e.g. ffi trampolines called from native
// code) we do have to perform type checks for all parameters.
//
// TODO(dartbug.com/40813): Remove the closure case when argument checks have
// been fully moved out of closures.
return !method.CanReceiveDynamicInvocation() &&
!(method.IsClosureFunction() &&
Function::ClosureBodiesContainNonCovariantTypeArgumentChecks());
return !method.CanReceiveDynamicInvocation();
}
// Returns true if the given method can skip type checks for all arguments
+8 -79
View File
@@ -22,7 +22,6 @@
#include "vm/compiler/cha.h"
#include "vm/compiler/compiler_pass.h"
#include "vm/compiler/compiler_state.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/flow_graph_builder.h"
#include "vm/compiler/frontend/kernel_to_il.h"
#include "vm/compiler/jit/jit_call_specializer.h"
@@ -84,7 +83,6 @@ DEFINE_FLAG(bool,
"Trace only optimizing compiler operations.");
DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler.");
DECLARE_FLAG(bool, enable_interpreter);
DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
DECLARE_FLAG(bool, trace_failed_optimization_attempts);
@@ -215,25 +213,7 @@ DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
ASSERT(thread->IsMutatorThread());
const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
Object& result = Object::Handle(zone);
if (FLAG_enable_interpreter && function.IsBytecodeAllowed(zone)) {
if (!function.HasBytecode()) {
result = kernel::BytecodeReader::ReadFunctionBytecode(thread, function);
if (!result.IsNull()) {
Exceptions::PropagateError(Error::Cast(result));
}
}
if (function.HasBytecode() && (FLAG_compilation_counter_threshold != 0)) {
// If interpreter is enabled and there is bytecode, LazyCompile stub
// (which calls CompileFunction) should proceed to InterpretCall in order
// to enter interpreter. In such case, compilation is postponed and
// triggered by interpreter later via CompileInterpretedFunction.
return;
}
// Fall back to compilation.
} else {
ASSERT(!function.HasCode());
}
ASSERT(!function.HasCode());
result = Compiler::CompileFunction(thread, function);
if (result.IsError()) {
@@ -495,13 +475,6 @@ void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped(
Compiler::AbortBackgroundCompilation(
DeoptId::kNone, "Optimizing Background compilation is being stopped");
}
} else {
if (FLAG_enable_interpreter &&
!isolate()->background_compiler()->is_running()) {
// The background compiler is being stopped.
Compiler::AbortBackgroundCompilation(
DeoptId::kNone, "Background compilation is being stopped");
}
}
}
@@ -783,9 +756,8 @@ static ObjectPtr CompileFunctionHelper(CompilationPipeline* pipeline,
function.set_is_background_optimizable(false);
// Trigger another optimization soon on the main thread.
function.SetUsageCounter(optimized
? FLAG_optimization_counter_threshold
: FLAG_compilation_counter_threshold);
function.SetUsageCounter(
optimized ? FLAG_optimization_counter_threshold : 0);
return Error::null();
} else if (error.IsLanguageError() &&
LanguageError::Cast(error).kind() == Report::kBailout) {
@@ -942,8 +914,6 @@ ObjectPtr Compiler::CompileOptimizedFunction(Thread* thread,
TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
#endif // defined(SUPPORT_TIMELINE)
ASSERT(function.ShouldCompilerOptimize());
CompilationPipeline* pipeline =
CompilationPipeline::New(thread->zone(), function);
return CompileFunctionHelper(pipeline, function, /* optimized = */ true,
@@ -978,21 +948,8 @@ void Compiler::ComputeLocalVarDescriptors(const Code& code) {
auto& var_descs = LocalVarDescriptors::Handle(zone);
if (function.is_declared_in_bytecode()) {
if (function.HasBytecode()) {
const auto& bytecode = Bytecode::Handle(zone, function.bytecode());
var_descs = bytecode.GetLocalVarDescriptors();
LocalVarDescriptorsBuilder builder;
builder.AddDeoptIdToContextLevelMappings(context_level_array);
builder.AddAll(zone, var_descs);
var_descs = builder.Done();
} else {
var_descs = Object::empty_var_descriptors().raw();
}
} else {
var_descs = parsed_function->scope()->GetVarDescriptors(
function, context_level_array);
}
var_descs = parsed_function->scope()->GetVarDescriptors(
function, context_level_array);
ASSERT(!var_descs.IsNull());
code.set_var_descriptors(var_descs);
@@ -1026,30 +983,6 @@ ErrorPtr Compiler::CompileAllFunctions(const Class& cls) {
return Error::null();
}
ErrorPtr Compiler::ReadAllBytecode(const Class& cls) {
Thread* thread = Thread::Current();
ASSERT(thread->IsMutatorThread());
Zone* zone = thread->zone();
Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
ASSERT(error.IsNull());
Array& functions = Array::Handle(zone, cls.current_functions());
Function& func = Function::Handle(zone);
// Compile all the regular functions.
for (int i = 0; i < functions.Length(); i++) {
func ^= functions.At(i);
ASSERT(!func.IsNull());
if (func.IsBytecodeAllowed(zone) && !func.HasBytecode() &&
!func.HasCode()) {
ErrorPtr error =
kernel::BytecodeReader::ReadFunctionBytecode(thread, func);
if (error != Error::null()) {
return error;
}
}
}
return Error::null();
}
void Compiler::AbortBackgroundCompilation(intptr_t deopt_id, const char* msg) {
if (FLAG_trace_compiler) {
THR_Print("ABORT background compilation: %s\n", msg);
@@ -1209,13 +1142,9 @@ void BackgroundCompiler::Run() {
}
}
while (!function.IsNull()) {
if (is_optimizing()) {
Compiler::CompileOptimizedFunction(thread, function,
Compiler::kNoOSRDeoptId);
} else {
ASSERT(FLAG_enable_interpreter);
Compiler::CompileFunction(thread, function);
}
ASSERT(is_optimizing());
Compiler::CompileOptimizedFunction(thread, function,
Compiler::kNoOSRDeoptId);
QueueElement* qelem = NULL;
{
-21
View File
@@ -84,8 +84,6 @@ class Compiler : public AllStatic {
static ObjectPtr CompileFunction(Thread* thread, const Function& function);
// Generates unoptimized code if not present, current code is unchanged.
// Bytecode is considered unoptimized code.
// TODO(regis): Revisit when deoptimizing mixed bytecode and jitted code.
static ErrorPtr EnsureUnoptimizedCode(Thread* thread,
const Function& function);
@@ -108,9 +106,6 @@ class Compiler : public AllStatic {
// Returns Error::null() if there is no compilation error.
static ErrorPtr CompileAllFunctions(const Class& cls);
// Eagerly read all bytecode.
static ErrorPtr ReadAllBytecode(const Class& cls);
// Notify the compiler that background (optimized) compilation has failed
// because the mutator thread changed the state (e.g., deoptimization,
// deferred loading). The background compilation may retry to compile
@@ -129,36 +124,24 @@ class BackgroundCompiler {
static void Start(Isolate* isolate) {
ASSERT(Thread::Current()->IsMutatorThread());
if (FLAG_enable_interpreter && isolate->background_compiler() != NULL) {
isolate->background_compiler()->Start();
}
if (isolate->optimizing_background_compiler() != NULL) {
isolate->optimizing_background_compiler()->Start();
}
}
static void Stop(Isolate* isolate) {
ASSERT(Thread::Current()->IsMutatorThread());
if (FLAG_enable_interpreter && isolate->background_compiler() != NULL) {
isolate->background_compiler()->Stop();
}
if (isolate->optimizing_background_compiler() != NULL) {
isolate->optimizing_background_compiler()->Stop();
}
}
static void Enable(Isolate* isolate) {
ASSERT(Thread::Current()->IsMutatorThread());
if (FLAG_enable_interpreter && isolate->background_compiler() != NULL) {
isolate->background_compiler()->Enable();
}
if (isolate->optimizing_background_compiler() != NULL) {
isolate->optimizing_background_compiler()->Enable();
}
}
static void Disable(Isolate* isolate) {
ASSERT(Thread::Current()->IsMutatorThread());
if (FLAG_enable_interpreter && isolate->background_compiler() != NULL) {
isolate->background_compiler()->Disable();
}
if (isolate->optimizing_background_compiler() != NULL) {
isolate->optimizing_background_compiler()->Disable();
}
@@ -169,10 +152,6 @@ class BackgroundCompiler {
if (isolate->optimizing_background_compiler() != NULL) {
return isolate->optimizing_background_compiler()->IsDisabled();
}
} else {
if (FLAG_enable_interpreter && isolate->background_compiler() != NULL) {
return isolate->background_compiler()->IsDisabled();
}
}
return false;
}
+2 -10
View File
@@ -727,8 +727,8 @@ uword Thread::vm_execution_state() {
return dart::Thread::ExecutionState::kThreadInVM;
}
uword Thread::vm_tag_compiled_id() {
return dart::VMTag::kDartCompiledTagId;
uword Thread::vm_tag_dart_id() {
return dart::VMTag::kDartTagId;
}
uword Thread::exit_through_runtime_call() {
@@ -998,10 +998,6 @@ word KernelProgramInfo::NextFieldOffset() {
return -kWordSize;
}
word Bytecode::NextFieldOffset() {
return -kWordSize;
}
word PcDescriptors::NextFieldOffset() {
return -kWordSize;
}
@@ -1026,10 +1022,6 @@ word ContextScope::NextFieldOffset() {
return -kWordSize;
}
word ParameterTypeCheck::NextFieldOffset() {
return -kWordSize;
}
word UnlinkedCall::NextFieldOffset() {
return -kWordSize;
}
+1 -15
View File
@@ -807,12 +807,6 @@ class KernelProgramInfo : public AllStatic {
static word NextFieldOffset();
};
class Bytecode : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class PcDescriptors : public AllStatic {
public:
static word HeaderSize();
@@ -855,12 +849,6 @@ class ContextScope : public AllStatic {
static word NextFieldOffset();
};
class ParameterTypeCheck : public AllStatic {
public:
static word InstanceSize();
static word NextFieldOffset();
};
class UnlinkedCall : public AllStatic {
public:
static word InstanceSize();
@@ -1037,7 +1025,7 @@ class Thread : public AllStatic {
static word slow_type_test_entry_point_offset();
static word write_barrier_entry_point_offset();
static word vm_tag_offset();
static uword vm_tag_compiled_id();
static uword vm_tag_dart_id();
static word safepoint_state_offset();
static uword safepoint_state_unacquired();
@@ -1067,8 +1055,6 @@ class Thread : public AllStatic {
static word slow_type_test_stub_offset();
static word call_to_runtime_stub_offset();
static word invoke_dart_code_stub_offset();
static word interpret_call_entry_point_offset();
static word invoke_dart_code_from_bytecode_stub_offset();
static word late_initialization_error_shared_without_fpu_regs_stub_offset();
static word late_initialization_error_shared_with_fpu_regs_stub_offset();
static word null_error_shared_without_fpu_regs_stub_offset();
File diff suppressed because it is too large Load Diff
@@ -208,8 +208,6 @@
FIELD(Thread, float_not_address_offset) \
FIELD(Thread, float_zerow_address_offset) \
FIELD(Thread, global_object_pool_offset) \
FIELD(Thread, interpret_call_entry_point_offset) \
FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset) \
FIELD(Thread, invoke_dart_code_stub_offset) \
FIELD(Thread, exit_through_ffi_offset) \
FIELD(Thread, isolate_offset) \
@@ -301,7 +299,6 @@
SIZEOF(Array, InstanceSize, ArrayLayout) \
SIZEOF(Array, header_size, ArrayLayout) \
SIZEOF(Bool, InstanceSize, BoolLayout) \
SIZEOF(Bytecode, InstanceSize, BytecodeLayout) \
SIZEOF(Capability, InstanceSize, CapabilityLayout) \
SIZEOF(Class, InstanceSize, ClassLayout) \
SIZEOF(Closure, InstanceSize, ClosureLayout) \
@@ -347,7 +344,6 @@
SIZEOF(Object, InstanceSize, ObjectLayout) \
SIZEOF(ObjectPool, InstanceSize, ObjectPoolLayout) \
SIZEOF(OneByteString, InstanceSize, OneByteStringLayout) \
SIZEOF(ParameterTypeCheck, InstanceSize, ParameterTypeCheckLayout) \
SIZEOF(PatchClass, InstanceSize, PatchClassLayout) \
SIZEOF(PcDescriptors, HeaderSize, PcDescriptorsLayout) \
SIZEOF(Pointer, InstanceSize, PointerLayout) \
+2 -8
View File
@@ -84,14 +84,8 @@ void StubCodeCompiler::GenerateInitLateInstanceFieldStub(Assembler* assembler,
if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions) {
__ LoadField(CODE_REG,
FieldAddress(kFunctionReg, target::Function::code_offset()));
if (FLAG_enable_interpreter) {
// InterpretCall stub needs arguments descriptor for all function calls.
__ LoadObject(ARGS_DESC_REG,
CastHandle<Object>(OneArgArgumentsDescriptor()));
} else {
// Load a GC-safe value for the arguments descriptor (unused but tagged).
__ LoadImmediate(ARGS_DESC_REG, 0);
}
// Load a GC-safe value for the arguments descriptor (unused but tagged).
__ LoadImmediate(ARGS_DESC_REG, 0);
}
__ Call(FieldAddress(kFunctionReg, target::Function::entry_point_offset()));
__ Drop(1); // Drop argument.
+6 -244
View File
@@ -96,7 +96,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R8, VMTag::kDartCompiledTagId);
__ CompareImmediate(R8, VMTag::kDartTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -137,7 +137,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
__ blx(R9);
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
@@ -540,7 +540,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R8, VMTag::kDartCompiledTagId);
__ CompareImmediate(R8, VMTag::kDartTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -587,7 +587,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
__ blx(LR);
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
@@ -1230,7 +1230,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ LoadImmediate(R9, VMTag::kDartCompiledTagId);
__ LoadImmediate(R9, VMTag::kDartTagId);
__ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
// Load arguments descriptor array into R4, which is passed to Dart code.
@@ -1307,160 +1307,6 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ Ret();
}
// Called when invoking compiled Dart code from interpreted Dart code.
// Input parameters:
// LR : points to return address.
// R0 : raw code object of the Dart function to call.
// R1 : arguments raw descriptor array.
// R2 : address of first argument.
// R3 : current thread.
void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
__ Push(LR); // Marker for the profiler.
__ EnterFrame((1 << FP) | (1 << LR), 0);
// Push code object to PC marker slot.
__ ldr(IP,
Address(R3,
target::Thread::invoke_dart_code_from_bytecode_stub_offset()));
__ Push(IP);
// Save new context and C++ ABI callee-saved registers.
__ PushList(kAbiPreservedCpuRegs);
const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
if (TargetCPUFeatures::vfp_supported()) {
ASSERT(2 * kAbiPreservedFpuRegCount < 16);
// Save FPU registers. 2 D registers per Q register.
__ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
} else {
__ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
}
// Set up THR, which caches the current thread in Dart code.
if (THR != R3) {
__ mov(THR, Operand(R3));
}
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Save the current VMTag on the stack.
__ LoadFromOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
__ Push(R9);
// Save top resource and top exit frame info. Use R4-6 as temporary registers.
// StackFrameIterator reads the top exit frame info saved in this frame.
__ LoadFromOffset(kWord, R4, THR, target::Thread::top_resource_offset());
__ Push(R4);
__ LoadImmediate(R8, 0);
__ StoreToOffset(kWord, R8, THR, target::Thread::top_resource_offset());
__ LoadFromOffset(kWord, R8, THR, target::Thread::exit_through_ffi_offset());
__ Push(R8);
__ LoadImmediate(R8, 0);
__ StoreToOffset(kWord, R8, THR, target::Thread::exit_through_ffi_offset());
__ LoadFromOffset(kWord, R9, THR,
target::Thread::top_exit_frame_info_offset());
__ StoreToOffset(kWord, R8, THR,
target::Thread::top_exit_frame_info_offset());
// target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
// with the code below.
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -27);
#else
ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -28);
#endif
__ Push(R9);
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ LoadImmediate(R9, VMTag::kDartCompiledTagId);
__ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
// Load arguments descriptor array into R4, which is passed to Dart code.
__ mov(R4, Operand(R1));
// Load number of arguments into R9 and adjust count for type arguments.
__ ldr(R3,
FieldAddress(R4, target::ArgumentsDescriptor::type_args_len_offset()));
__ ldr(R9, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
__ cmp(R3, Operand(0));
__ AddImmediate(R9, R9, target::ToRawSmi(1),
NE); // Include the type arguments.
__ SmiUntag(R9);
// R2 points to first argument.
// Set up arguments for the Dart call.
Label push_arguments;
Label done_push_arguments;
__ CompareImmediate(R9, 0); // check if there are arguments.
__ b(&done_push_arguments, EQ);
__ LoadImmediate(R1, 0);
__ Bind(&push_arguments);
__ ldr(R3, Address(R2));
__ Push(R3);
__ AddImmediate(R2, target::kWordSize);
__ AddImmediate(R1, 1);
__ cmp(R1, Operand(R9));
__ b(&push_arguments, LT);
__ Bind(&done_push_arguments);
// Call the Dart code entrypoint.
__ LoadImmediate(PP, 0); // GC safe value into PP.
__ mov(CODE_REG, Operand(R0));
__ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
__ blx(R0); // R4 is the arguments descriptor array.
// Get rid of arguments pushed on the stack.
__ AddImmediate(
SP, FP,
target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
// Restore the saved top exit frame info and top resource back into the
// Isolate structure. Uses R9 as a temporary register for this.
__ Pop(R9);
__ StoreToOffset(kWord, R9, THR,
target::Thread::top_exit_frame_info_offset());
__ Pop(R9);
__ StoreToOffset(kWord, R9, THR, target::Thread::exit_through_ffi_offset());
__ Pop(R9);
__ StoreToOffset(kWord, R9, THR, target::Thread::top_resource_offset());
// Restore the current VMTag from the stack.
__ Pop(R4);
__ StoreToOffset(kWord, R4, THR, target::Thread::vm_tag_offset());
// Restore C++ ABI callee-saved registers.
if (TargetCPUFeatures::vfp_supported()) {
// Restore FPU registers. 2 D registers per Q register.
__ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
} else {
__ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
}
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Restore CPU registers.
__ PopList(kAbiPreservedCpuRegs);
__ set_constant_pool_allowed(false);
// Restore the frame pointer and return.
__ LeaveFrame((1 << FP) | (1 << LR));
__ Drop(1);
__ Ret();
}
// Helper to generate space allocation of context stub.
// This does not initialise the fields of the context.
// Input:
@@ -2695,94 +2541,10 @@ void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
__ PopList((1 << R0) | (1 << R4));
__ LeaveStubFrame();
// When using the interpreter, the function's code may now point to the
// InterpretCall stub. Make sure R0, R4 and R9 are preserved.
__ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
__ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
}
// Stub for interpreting a function call.
// R4: Arguments descriptor.
// R0: Function.
void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
__ EnterStubFrame();
#if defined(DEBUG)
{
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R8, VMTag::kDartCompiledTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
}
#endif
// Adjust arguments count for type arguments vector.
__ LoadFieldFromOffset(kWord, R2, R4,
target::ArgumentsDescriptor::count_offset());
__ SmiUntag(R2);
__ LoadFieldFromOffset(kWord, R1, R4,
target::ArgumentsDescriptor::type_args_len_offset());
__ cmp(R1, Operand(0));
__ AddImmediate(R2, R2, 1, NE); // Include the type arguments.
// Compute argv.
__ mov(R3, Operand(R2, LSL, 2));
__ add(R3, FP, Operand(R3));
__ AddImmediate(R3,
target::frame_layout.param_end_from_fp * target::kWordSize);
// Indicate decreasing memory addresses of arguments with negative argc.
__ rsb(R2, R2, Operand(0));
// Align frame before entering C++ world. Fifth argument passed on the stack.
__ ReserveAlignedFrameSpace(1 * target::kWordSize);
// Pass arguments in registers.
// R0: Function.
__ mov(R1, Operand(R4)); // Arguments descriptor.
// R2: Negative argc.
// R3: Argv.
__ str(THR, Address(SP, 0)); // Fifth argument: Thread.
// Save exit frame information to enable stack walking as we are about
// to transition to Dart VM C++ code.
__ StoreToOffset(kWord, FP, THR,
target::Thread::top_exit_frame_info_offset());
// Mark that the thread exited generated code through a runtime call.
__ LoadImmediate(R5, target::Thread::exit_through_runtime_call());
__ StoreToOffset(kWord, R5, THR, target::Thread::exit_through_ffi_offset());
// Mark that the thread is executing VM code.
__ LoadFromOffset(kWord, R5, THR,
target::Thread::interpret_call_entry_point_offset());
__ StoreToOffset(kWord, R5, THR, target::Thread::vm_tag_offset());
__ blx(R5);
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
__ LoadImmediate(R2, 0);
__ StoreToOffset(kWord, R2, THR, target::Thread::exit_through_ffi_offset());
// Reset exit frame information in Isolate's mutator thread structure.
__ StoreToOffset(kWord, R2, THR,
target::Thread::top_exit_frame_info_offset());
__ LeaveStubFrame();
__ Ret();
}
// R9: Contains an ICData.
void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
#if defined(PRODUCT)
@@ -3318,7 +3080,7 @@ void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
__ Bind(&exit_through_non_ffi);
// Set the tag.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
// Clear top exit frame.
__ LoadImmediate(R2, 0);
+6 -252
View File
@@ -91,7 +91,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(R8, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R8, VMTag::kDartCompiledTagId);
__ CompareImmediate(R8, VMTag::kDartTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -154,7 +154,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
// Retval is next to 1st argument.
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
@@ -622,7 +622,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(R6, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R6, VMTag::kDartCompiledTagId);
__ CompareImmediate(R6, VMTag::kDartTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -685,7 +685,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
__ RestorePinnedRegisters();
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
@@ -1358,7 +1358,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ LoadImmediate(R6, VMTag::kDartCompiledTagId);
__ LoadImmediate(R6, VMTag::kDartTagId);
__ StoreToOffset(R6, THR, target::Thread::vm_tag_offset());
// Load arguments descriptor array into R4, which is passed to Dart code.
@@ -1444,157 +1444,6 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ ret();
}
// Called when invoking compiled Dart code from interpreted Dart code.
// Input parameters:
// LR : points to return address.
// R0 : raw code object of the Dart function to call.
// R1 : arguments raw descriptor array.
// R2 : address of first argument.
// R3 : current thread.
void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
// Copy the C stack pointer (CSP/R31) into the stack pointer we'll actually
// use to access the stack (SP/R15) and set the C stack pointer to near the
// stack limit, loaded from the Thread held in R3, to prevent signal handlers
// from over-writing Dart frames.
__ mov(SP, CSP);
__ SetupCSPFromThread(R3);
__ Push(LR); // Marker for the profiler.
__ EnterFrame(0);
// Push code object to PC marker slot.
__ ldr(TMP,
Address(R3,
target::Thread::invoke_dart_code_from_bytecode_stub_offset()));
__ Push(TMP);
#if defined(TARGET_OS_FUCHSIA)
__ str(R18, Address(R3, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
__ PushNativeCalleeSavedRegisters();
// Set up THR, which caches the current thread in Dart code.
if (THR != R3) {
__ mov(THR, R3);
}
// Refresh pinned registers values (inc. write barrier mask and null object).
__ RestorePinnedRegisters();
// Save the current VMTag on the stack.
__ LoadFromOffset(R4, THR, target::Thread::vm_tag_offset());
__ Push(R4);
// Save top resource and top exit frame info. Use R6 as a temporary register.
// StackFrameIterator reads the top exit frame info saved in this frame.
__ LoadFromOffset(R6, THR, target::Thread::top_resource_offset());
__ StoreToOffset(ZR, THR, target::Thread::top_resource_offset());
__ Push(R6);
__ LoadFromOffset(R6, THR, target::Thread::exit_through_ffi_offset());
__ Push(R6);
__ LoadImmediate(R6, 0);
__ StoreToOffset(R6, THR, target::Thread::exit_through_ffi_offset());
__ LoadFromOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
__ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
// target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
// with the code below.
#if defined(TARGET_OS_FUCHSIA)
ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -24);
#else
ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -23);
#endif
__ Push(R6);
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ LoadImmediate(R6, VMTag::kDartCompiledTagId);
__ StoreToOffset(R6, THR, target::Thread::vm_tag_offset());
// Load arguments descriptor array into R4, which is passed to Dart code.
__ mov(R4, R1);
// Load number of arguments into R5 and adjust count for type arguments.
__ LoadFieldFromOffset(R5, R4, target::ArgumentsDescriptor::count_offset());
__ LoadFieldFromOffset(R3, R4,
target::ArgumentsDescriptor::type_args_len_offset());
__ AddImmediate(TMP, R5, 1); // Include the type arguments.
__ cmp(R3, Operand(0));
__ csinc(R5, R5, TMP, EQ); // R5 <- (R3 == 0) ? R5 : TMP + 1 (R5 : R5 + 2).
__ SmiUntag(R5);
// R2 points to first argument.
// Set up arguments for the Dart call.
Label push_arguments;
Label done_push_arguments;
__ cmp(R5, Operand(0));
__ b(&done_push_arguments, EQ); // check if there are arguments.
__ LoadImmediate(R1, 0);
__ Bind(&push_arguments);
__ ldr(R3, Address(R2));
__ Push(R3);
__ add(R1, R1, Operand(1));
__ add(R2, R2, Operand(target::kWordSize));
__ cmp(R1, Operand(R5));
__ b(&push_arguments, LT);
__ Bind(&done_push_arguments);
// We now load the pool pointer(PP) with a GC safe value as we are about to
// invoke dart code. We don't need a real object pool here.
// Smi zero does not work because ARM64 assumes PP to be untagged.
__ LoadObject(PP, NullObject());
// Call the Dart code entrypoint.
__ mov(CODE_REG, R0);
__ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
__ blr(R0); // R4 is the arguments descriptor array.
// Get rid of arguments pushed on the stack.
__ AddImmediate(
SP, FP,
target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
// Restore the saved top exit frame info and top resource back into the
// Isolate structure. Uses R6 as a temporary register for this.
__ Pop(R6);
__ StoreToOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
__ Pop(R6);
__ StoreToOffset(R6, THR, target::Thread::exit_through_ffi_offset());
__ Pop(R6);
__ StoreToOffset(R6, THR, target::Thread::top_resource_offset());
// Restore the current VMTag from the stack.
__ Pop(R4);
__ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
#if defined(TARGET_OS_FUCHSIA)
__ mov(R3, THR);
#endif
__ PopNativeCalleeSavedRegisters(); // Clobbers THR
#if defined(TARGET_OS_FUCHSIA)
__ str(R18, Address(R3, target::Thread::saved_shadow_call_stack_offset()));
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Restore the frame pointer and C stack pointer and return.
__ LeaveFrame();
__ Drop(1);
__ RestoreCSP();
__ ret();
}
// Helper to generate space allocation of context stub.
// This does not initialise the fields of the context.
// Input:
@@ -2858,106 +2707,11 @@ void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
__ Pop(R4); // Restore arg desc.
__ LeaveStubFrame();
// When using the interpreter, the function's code may now point to the
// InterpretCall stub. Make sure R0, R4, and R5 are preserved.
__ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
__ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
__ br(R2);
}
// Stub for interpreting a function call.
// R4: Arguments descriptor.
// R0: Function.
void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
__ SetPrologueOffset();
__ EnterStubFrame();
#if defined(DEBUG)
{
Label ok;
// Check that we are always entering from Dart code.
__ LoadFromOffset(R8, THR, target::Thread::vm_tag_offset());
__ CompareImmediate(R8, VMTag::kDartCompiledTagId);
__ b(&ok, EQ);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
}
#endif
// Adjust arguments count for type arguments vector.
__ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::count_offset());
__ SmiUntag(R2);
__ LoadFieldFromOffset(R1, R4,
target::ArgumentsDescriptor::type_args_len_offset());
__ cmp(R1, Operand(0));
__ csinc(R2, R2, R2, EQ); // R2 <- (R1 == 0) ? R2 : R2 + 1.
// Compute argv.
__ add(R3, ZR, Operand(R2, LSL, 3));
__ add(R3, FP, Operand(R3));
__ AddImmediate(R3,
target::frame_layout.param_end_from_fp * target::kWordSize);
// Indicate decreasing memory addresses of arguments with negative argc.
__ neg(R2, R2);
// Align frame before entering C++ world. No shadow stack space required.
__ ReserveAlignedFrameSpace(0 * target::kWordSize);
// Pass arguments in registers.
// R0: Function.
__ mov(R1, R4); // Arguments descriptor.
// R2: Negative argc.
// R3: Argv.
__ mov(R4, THR); // Thread.
// Save exit frame information to enable stack walking as we are about
// to transition to Dart VM C++ code.
__ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
// Mark that the thread exited generated code through a runtime call.
__ LoadImmediate(R5, target::Thread::exit_through_runtime_call());
__ StoreToOffset(R5, THR, target::Thread::exit_through_ffi_offset());
// Mark that the thread is executing VM code.
__ LoadFromOffset(R5, THR,
target::Thread::interpret_call_entry_point_offset());
__ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
// We are entering runtime code, so the C stack pointer must be restored from
// the stack limit to the top of the stack. We cache the stack limit address
// in a callee-saved register.
__ mov(R25, CSP);
__ mov(CSP, SP);
__ blr(R5);
// Restore SP and CSP.
__ mov(SP, CSP);
__ mov(CSP, R25);
// Refresh pinned registers values (inc. write barrier mask and null object).
__ RestorePinnedRegisters();
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
// Mark that the thread has not exited generated Dart code.
__ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
// Reset exit frame information in Isolate's mutator thread structure.
__ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
__ LeaveStubFrame();
__ ret();
}
// R5: Contains an ICData.
void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
#if defined(PRODUCT)
@@ -3484,7 +3238,7 @@ void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
// Refresh pinned registers values (inc. write barrier mask and null object).
__ RestorePinnedRegisters();
// Set the tag.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ LoadImmediate(R2, VMTag::kDartTagId);
__ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
// Clear top exit frame.
__ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+6 -210
View File
@@ -93,7 +93,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
{
Label ok;
// Check that we are always entering from Dart code.
__ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -126,7 +126,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
__ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
__ call(ECX);
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Mark that the thread has not exited generated Dart code.
__ movl(Address(THR, target::Thread::exit_through_ffi_offset()),
@@ -364,7 +364,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
{
Label ok;
// Check that we are always entering from Dart code.
__ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
@@ -400,7 +400,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
__ movl(Address(ESP, target::kWordSize), ECX); // Function to call.
__ call(wrapper_address);
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Mark that the thread has not exited generated Dart code.
__ movl(Address(THR, target::Thread::exit_through_ffi_offset()),
@@ -955,7 +955,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Load arguments descriptor array into EDX.
__ movl(EDX, Address(EBP, kArgumentsDescOffset));
@@ -1029,134 +1029,6 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ ret();
}
// Called when invoking compiled Dart code from interpreted Dart code.
// Input parameters:
// ESP : points to return address.
// ESP + 4 : target raw code
// ESP + 8 : arguments raw descriptor array.
// ESP + 12: address of first argument.
// ESP + 16 : current thread.
void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
Assembler* assembler) {
const intptr_t kTargetCodeOffset = 3 * target::kWordSize;
const intptr_t kArgumentsDescOffset = 4 * target::kWordSize;
const intptr_t kArgumentsOffset = 5 * target::kWordSize;
const intptr_t kThreadOffset = 6 * target::kWordSize;
__ pushl(Address(ESP, 0)); // Marker for the profiler.
__ EnterFrame(0);
// Push code object to PC marker slot.
__ movl(EAX, Address(EBP, kThreadOffset));
__ pushl(Address(EAX, target::Thread::invoke_dart_code_stub_offset()));
// Save C++ ABI callee-saved registers.
__ pushl(EBX);
__ pushl(ESI);
__ pushl(EDI);
// Set up THR, which caches the current thread in Dart code.
__ movl(THR, EAX);
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Save the current VMTag on the stack.
__ movl(ECX, Assembler::VMTagAddress());
__ pushl(ECX);
// Save top resource and top exit frame info. Use EDX as a temporary register.
// StackFrameIterator reads the top exit frame info saved in this frame.
__ movl(EDX, Address(THR, target::Thread::top_resource_offset()));
__ pushl(EDX);
__ movl(Address(THR, target::Thread::top_resource_offset()), Immediate(0));
__ movl(EAX, Address(THR, target::Thread::exit_through_ffi_offset()));
__ pushl(EAX);
__ movl(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(0));
// The constant target::frame_layout.exit_link_slot_from_entry_fp must be
// kept in sync with the code below.
ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -8);
__ movl(EDX, Address(THR, target::Thread::top_exit_frame_info_offset()));
__ pushl(EDX);
__ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
// Load arguments descriptor array into EDX.
__ movl(EDX, Address(EBP, kArgumentsDescOffset));
// Load number of arguments into EBX and adjust count for type arguments.
__ movl(EBX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
__ cmpl(
FieldAddress(EDX, target::ArgumentsDescriptor::type_args_len_offset()),
Immediate(0));
Label args_count_ok;
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
__ addl(EBX, Immediate(target::ToRawSmi(1))); // Include the type arguments.
__ Bind(&args_count_ok);
// Save number of arguments as Smi on stack, replacing ArgumentsDesc.
__ movl(Address(EBP, kArgumentsDescOffset), EBX);
__ SmiUntag(EBX);
// Set up arguments for the dart call.
Label push_arguments;
Label done_push_arguments;
__ testl(EBX, EBX); // check if there are arguments.
__ j(ZERO, &done_push_arguments, Assembler::kNearJump);
__ movl(EAX, Immediate(0));
// Compute address of 'arguments array' data area into EDI.
__ movl(EDI, Address(EBP, kArgumentsOffset));
__ Bind(&push_arguments);
__ movl(ECX, Address(EDI, EAX, TIMES_4, 0));
__ pushl(ECX);
__ incl(EAX);
__ cmpl(EAX, EBX);
__ j(LESS, &push_arguments, Assembler::kNearJump);
__ Bind(&done_push_arguments);
// Call the dart code entrypoint.
__ movl(EAX, Address(EBP, kTargetCodeOffset));
__ call(FieldAddress(EAX, target::Code::entry_point_offset()));
// Read the saved number of passed arguments as Smi.
__ movl(EDX, Address(EBP, kArgumentsDescOffset));
// Get rid of arguments pushed on the stack.
__ leal(ESP, Address(ESP, EDX, TIMES_2, 0)); // EDX is a Smi.
// Restore the saved top exit frame info and top resource back into the
// Isolate structure.
__ popl(Address(THR, target::Thread::top_exit_frame_info_offset()));
__ popl(Address(THR, target::Thread::exit_through_ffi_offset()));
__ popl(Address(THR, target::Thread::top_resource_offset()));
// Restore the current VMTag from the stack.
__ popl(Assembler::VMTagAddress());
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Restore C++ ABI callee-saved registers.
__ popl(EDI);
__ popl(ESI);
__ popl(EBX);
// Restore the frame pointer.
__ LeaveFrame();
__ popl(ECX);
__ ret();
}
// Helper to generate space allocation of context stub.
// This does not initialise the fields of the context.
// Input:
@@ -2231,85 +2103,9 @@ void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
__ popl(EDX); // Restore arguments descriptor array.
__ LeaveFrame();
// When using the interpreter, the function's code may now point to the
// InterpretCall stub. Make sure EAX, ECX, and EDX are preserved.
__ jmp(FieldAddress(EAX, target::Function::entry_point_offset()));
}
// Stub for interpreting a function call.
// EDX: Arguments descriptor.
// EAX: Function.
void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
__ EnterStubFrame();
#if defined(DEBUG)
{
Label ok;
// Check that we are always entering from Dart code.
__ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
}
#endif
// Adjust arguments count for type arguments vector.
__ movl(ECX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
__ SmiUntag(ECX);
__ cmpl(
FieldAddress(EDX, target::ArgumentsDescriptor::type_args_len_offset()),
Immediate(0));
Label args_count_ok;
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
__ incl(ECX);
__ Bind(&args_count_ok);
// Compute argv.
__ leal(EBX,
Address(EBP, ECX, TIMES_4,
target::frame_layout.param_end_from_fp * target::kWordSize));
// Indicate decreasing memory addresses of arguments with negative argc.
__ negl(ECX);
__ pushl(THR); // Arg 4: Thread.
__ pushl(EBX); // Arg 3: Argv.
__ pushl(ECX); // Arg 2: Negative argc.
__ pushl(EDX); // Arg 1: Arguments descriptor
__ pushl(EAX); // Arg 0: Function
// Save exit frame information to enable stack walking as we are about
// to transition to Dart VM C++ code.
__ movl(Address(THR, target::Thread::top_exit_frame_info_offset()), EBP);
// Mark that the thread exited generated code through a runtime call.
__ movl(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(target::Thread::exit_through_runtime_call()));
// Mark that the thread is executing VM code.
__ movl(EAX,
Address(THR, target::Thread::interpret_call_entry_point_offset()));
__ movl(Assembler::VMTagAddress(), EAX);
__ call(EAX);
__ Drop(5);
// Mark that the thread is executing Dart code.
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
// Mark that the thread has not exited generated Dart code.
__ movl(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(0));
// Reset exit frame information in Isolate's mutator thread structure.
__ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
__ LeaveFrame();
__ ret();
}
// ECX: Contains an ICData.
void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
#if defined(PRODUCT)
@@ -2658,7 +2454,7 @@ void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
__ Bind(&exit_through_non_ffi);
// Set tag.
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Clear top exit frame.
__ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
+6 -262
View File
@@ -96,7 +96,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
{
Label ok;
// Check that we are always entering from Dart code.
__ movq(RAX, Immediate(VMTag::kDartCompiledTagId));
__ movq(RAX, Immediate(VMTag::kDartTagId));
__ cmpq(RAX, Assembler::VMTagAddress());
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
@@ -137,7 +137,7 @@ void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
__ CallCFunction(RBX);
// Mark that the thread is executing Dart code.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Mark that the thread has not exited generated Dart code.
__ movq(Address(THR, target::Thread::exit_through_ffi_offset()),
@@ -575,7 +575,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
{
Label ok;
// Check that we are always entering from Dart code.
__ movq(R8, Immediate(VMTag::kDartCompiledTagId));
__ movq(R8, Immediate(VMTag::kDartTagId));
__ cmpq(R8, Assembler::VMTagAddress());
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
@@ -614,7 +614,7 @@ static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
__ CallCFunction(RAX);
// Mark that the thread is executing Dart code.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Mark that the thread has not exited generated Dart code.
__ movq(Address(THR, target::Thread::exit_through_ffi_offset()),
@@ -1287,7 +1287,7 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Load arguments descriptor array into R10, which is passed to Dart code.
__ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
@@ -1367,172 +1367,6 @@ void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
__ ret();
}
// Called when invoking compiled Dart code from interpreted Dart code.
// Input parameters:
// RSP : points to return address.
// RDI : target raw code
// RSI : arguments raw descriptor array.
// RDX : address of first argument.
// RCX : current thread.
void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
__ pushq(Address(RSP, 0)); // Marker for the profiler.
__ EnterFrame(0);
const Register kTargetCodeReg = CallingConventions::kArg1Reg;
const Register kArgDescReg = CallingConventions::kArg2Reg;
const Register kArg0Reg = CallingConventions::kArg3Reg;
const Register kThreadReg = CallingConventions::kArg4Reg;
// Push code object to PC marker slot.
__ pushq(
Address(kThreadReg,
target::Thread::invoke_dart_code_from_bytecode_stub_offset()));
// At this point, the stack looks like:
// | stub code object
// | saved RBP | <-- RBP
// | saved PC (return to interpreter's InvokeCompiled) |
const intptr_t kInitialOffset = 2;
// Save arguments descriptor array, later replaced by Smi argument count.
const intptr_t kArgumentsDescOffset = -(kInitialOffset)*target::kWordSize;
__ pushq(kArgDescReg);
// Save C++ ABI callee-saved registers.
__ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
CallingConventions::kCalleeSaveXmmRegisters);
// If any additional (or fewer) values are pushed, the offsets in
// target::frame_layout.exit_link_slot_from_entry_fp will need to be changed.
// Set up THR, which caches the current thread in Dart code.
if (THR != kThreadReg) {
__ movq(THR, kThreadReg);
}
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Save the current VMTag on the stack.
__ movq(RAX, Assembler::VMTagAddress());
__ pushq(RAX);
// Save top resource and top exit frame info. Use RAX as a temporary register.
// StackFrameIterator reads the top exit frame info saved in this frame.
__ movq(RAX, Address(THR, target::Thread::top_resource_offset()));
__ pushq(RAX);
__ movq(Address(THR, target::Thread::top_resource_offset()), Immediate(0));
__ movq(RAX, Address(THR, target::Thread::exit_through_ffi_offset()));
__ pushq(RAX);
__ movq(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(0));
__ movq(RAX, Address(THR, target::Thread::top_exit_frame_info_offset()));
__ pushq(RAX);
__ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
// The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
// in sync with the code below.
#if defined(DEBUG)
{
Label ok;
__ leaq(RAX,
Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
target::kWordSize));
__ cmpq(RAX, RSP);
__ j(EQUAL, &ok);
__ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
__ Bind(&ok);
}
#endif
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
// Load arguments descriptor array into R10, which is passed to Dart code.
__ movq(R10, kArgDescReg);
// Push arguments. At this point we only need to preserve kTargetCodeReg.
ASSERT(kTargetCodeReg != RDX);
// Load number of arguments into RBX and adjust count for type arguments.
__ movq(RBX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
__ cmpq(
FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
Immediate(0));
Label args_count_ok;
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
__ addq(RBX, Immediate(target::ToRawSmi(1))); // Include the type arguments.
__ Bind(&args_count_ok);
// Save number of arguments as Smi on stack, replacing saved ArgumentsDesc.
__ movq(Address(RBP, kArgumentsDescOffset), RBX);
__ SmiUntag(RBX);
// Compute address of first argument into RDX.
if (kArg0Reg != RDX) { // Different registers on WIN64.
__ movq(RDX, kArg0Reg);
}
// Set up arguments for the Dart call.
Label push_arguments;
Label done_push_arguments;
__ j(ZERO, &done_push_arguments, Assembler::kNearJump);
__ LoadImmediate(RAX, Immediate(0));
__ Bind(&push_arguments);
__ pushq(Address(RDX, RAX, TIMES_8, 0));
__ incq(RAX);
__ cmpq(RAX, RBX);
__ j(LESS, &push_arguments, Assembler::kNearJump);
__ Bind(&done_push_arguments);
// Call the Dart code entrypoint.
__ xorq(PP, PP); // GC-safe value into PP.
__ movq(CODE_REG, kTargetCodeReg);
__ movq(kTargetCodeReg,
FieldAddress(CODE_REG, target::Code::entry_point_offset()));
__ call(kTargetCodeReg); // R10 is the arguments descriptor array.
// Read the saved number of passed arguments as Smi.
__ movq(RDX, Address(RBP, kArgumentsDescOffset));
// Get rid of arguments pushed on the stack.
__ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi.
// Restore the saved top exit frame info and top resource back into the
// Isolate structure.
__ popq(Address(THR, target::Thread::top_exit_frame_info_offset()));
__ popq(Address(THR, target::Thread::exit_through_ffi_offset()));
__ popq(Address(THR, target::Thread::top_resource_offset()));
// Restore the current VMTag from the stack.
__ popq(Assembler::VMTagAddress());
#if defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
// Restore C++ ABI callee-saved registers.
__ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
CallingConventions::kCalleeSaveXmmRegisters);
__ set_constant_pool_allowed(false);
// Restore the frame pointer.
__ LeaveFrame();
__ popq(RCX);
__ ret();
}
// Helper to generate space allocation of context stub.
// This does not initialise the fields of the context.
// Input:
@@ -2812,101 +2646,11 @@ void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
__ popq(R10); // Restore arguments descriptor array.
__ LeaveStubFrame();
// When using the interpreter, the function's code may now point to the
// InterpretCall stub. Make sure RAX, R10, and RBX are preserved.
__ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
__ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
__ jmp(RCX);
}
// Stub for interpreting a function call.
// R10: Arguments descriptor.
// RAX: Function.
void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
if (FLAG_precompiled_mode) {
__ Stop("Not using interpreter");
return;
}
__ EnterStubFrame();
#if defined(DEBUG)
{
Label ok;
// Check that we are always entering from Dart code.
__ movq(R8, Immediate(VMTag::kDartCompiledTagId));
__ cmpq(R8, Assembler::VMTagAddress());
__ j(EQUAL, &ok, Assembler::kNearJump);
__ Stop("Not coming from Dart code.");
__ Bind(&ok);
}
#endif
// Adjust arguments count for type arguments vector.
__ movq(R11, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
__ SmiUntag(R11);
__ cmpq(
FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
Immediate(0));
Label args_count_ok;
__ j(EQUAL, &args_count_ok, Assembler::kNearJump);
__ incq(R11);
__ Bind(&args_count_ok);
// Compute argv.
__ leaq(R12,
Address(RBP, R11, TIMES_8,
target::frame_layout.param_end_from_fp * target::kWordSize));
// Indicate decreasing memory addresses of arguments with negative argc.
__ negq(R11);
// Reserve shadow space for args and align frame before entering C++ world.
__ subq(RSP, Immediate(5 * target::kWordSize));
if (OS::ActivationFrameAlignment() > 1) {
__ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
}
__ movq(CallingConventions::kArg1Reg, RAX); // Function.
__ movq(CallingConventions::kArg2Reg, R10); // Arguments descriptor.
__ movq(CallingConventions::kArg3Reg, R11); // Negative argc.
__ movq(CallingConventions::kArg4Reg, R12); // Argv.
#if defined(TARGET_OS_WINDOWS)
__ movq(Address(RSP, 0 * target::kWordSize), THR); // Thread.
#else
__ movq(CallingConventions::kArg5Reg, THR); // Thread.
#endif
// Save exit frame information to enable stack walking as we are about
// to transition to Dart VM C++ code.
__ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
// Mark that the thread exited generated code through a runtime call.
__ movq(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(target::Thread::exit_through_runtime_call()));
// Mark that the thread is executing VM code.
__ movq(RAX,
Address(THR, target::Thread::interpret_call_entry_point_offset()));
__ movq(Assembler::VMTagAddress(), RAX);
__ call(RAX);
// Mark that the thread is executing Dart code.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
// Mark that the thread has not exited generated Dart code.
__ movq(Address(THR, target::Thread::exit_through_ffi_offset()),
Immediate(0));
// Reset exit frame information in Isolate's mutator thread structure.
__ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
__ LeaveStubFrame();
__ ret();
}
// RBX: Contains an ICData.
// TOS(0): return address (Dart code).
void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
@@ -3422,7 +3166,7 @@ void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
__ Bind(&exit_through_non_ffi);
// Set the tag.
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
// Clear top exit frame.
__ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
+2 -25
View File
@@ -6,7 +6,6 @@
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/code_patcher.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/dart_api_impl.h"
#include "vm/heap/safepoint.h"
#include "vm/kernel_isolate.h"
@@ -126,30 +125,8 @@ ISOLATE_UNIT_TEST_CASE(CompileFunctionOnHelperThread) {
Function& func =
Function::Handle(cls.LookupStaticFunction(function_foo_name));
EXPECT(!func.HasCode());
if (!FLAG_enable_interpreter) {
CompilerTest::TestCompileFunction(func);
EXPECT(func.HasCode());
return;
}
// Bytecode loading must happen on the main thread. Ensure the bytecode is
// loaded before asking for an unoptimized compile on a background thread.
kernel::BytecodeReader::ReadFunctionBytecode(thread, func);
#if !defined(PRODUCT)
// Constant in product mode.
FLAG_background_compilation = true;
#endif
Isolate* isolate = thread->isolate();
BackgroundCompiler::Start(isolate);
isolate->background_compiler()->Compile(func);
Monitor* m = new Monitor();
{
MonitorLocker ml(m);
while (!func.HasCode()) {
ml.WaitWithSafepointCheck(thread, 1);
}
}
delete m;
BackgroundCompiler::Stop(isolate);
CompilerTest::TestCompileFunction(func);
EXPECT(func.HasCode());
}
ISOLATE_UNIT_TEST_CASE(RegenerateAllocStubs) {
-76
View File
@@ -1,76 +0,0 @@
// Copyright (c) 2019, 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.
#define RUNTIME_VM_CONSTANTS_H_ // To work around include guard.
#include "vm/constants_kbc.h"
namespace dart {
static const intptr_t kInstructionSize0 = 1;
static const intptr_t kInstructionSizeA = 2;
static const intptr_t kInstructionSizeD = 2;
static const intptr_t kInstructionSizeWideD = 5;
static const intptr_t kInstructionSizeX = 2;
static const intptr_t kInstructionSizeWideX = 5;
static const intptr_t kInstructionSizeT = 2;
static const intptr_t kInstructionSizeWideT = 4;
static const intptr_t kInstructionSizeA_E = 3;
static const intptr_t kInstructionSizeWideA_E = 6;
static const intptr_t kInstructionSizeA_Y = 3;
static const intptr_t kInstructionSizeWideA_Y = 6;
static const intptr_t kInstructionSizeD_F = 3;
static const intptr_t kInstructionSizeWideD_F = 6;
static const intptr_t kInstructionSizeA_B_C = 4;
const intptr_t KernelBytecode::kInstructionSize[] = {
#define SIZE_ORDN(encoding) kInstructionSize##encoding
#define SIZE_WIDE(encoding) kInstructionSizeWide##encoding
#define SIZE_RESV(encoding) SIZE_ORDN(encoding)
#define SIZE(name, encoding, kind, op1, op2, op3) SIZE_##kind(encoding),
KERNEL_BYTECODES_LIST(SIZE)
#undef SIZE_ORDN
#undef SIZE_WIDE
#undef SIZE_RESV
#undef SIZE
};
#define DECLARE_INSTRUCTIONS(name, fmt, kind, fmta, fmtb, fmtc) \
static const KBCInstr k##name##Instructions[] = { \
KernelBytecode::k##name, \
KernelBytecode::kReturnTOS, \
};
INTERNAL_KERNEL_BYTECODES_LIST(DECLARE_INSTRUCTIONS)
#undef DECLARE_INSTRUCTIONS
void KernelBytecode::GetVMInternalBytecodeInstructions(
Opcode opcode,
const KBCInstr** instructions,
intptr_t* instructions_size) {
switch (opcode) {
#define CASE(name, fmt, kind, fmta, fmtb, fmtc) \
case k##name: \
*instructions = k##name##Instructions; \
*instructions_size = sizeof(k##name##Instructions); \
return;
INTERNAL_KERNEL_BYTECODES_LIST(CASE)
#undef CASE
default:
UNREACHABLE();
}
}
static const KBCInstr kNativeCallToGrowableListReturnTrampoline[] = {
KernelBytecode::kDirectCall,
0, // target (doesn't matter)
KernelBytecode::kNativeCallToGrowableListArgc, // number of arguments
KernelBytecode::kReturnTOS,
};
const KBCInstr* KernelBytecode::GetNativeCallToGrowableListReturnTrampoline() {
return KernelBytecode::Next(&kNativeCallToGrowableListReturnTrampoline[0]);
}
} // namespace dart
File diff suppressed because it is too large Load Diff
-25
View File
@@ -9,7 +9,6 @@
#include "vm/debugger.h"
#include "vm/dispatch_table.h"
#include "vm/heap/safepoint.h"
#include "vm/interpreter.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/runtime_entry.h"
@@ -19,13 +18,11 @@
#include "vm/zone_text_buffer.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/jit/compiler.h"
#endif // !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
DECLARE_FLAG(bool, enable_interpreter);
DECLARE_FLAG(bool, precompiled_mode);
// A cache of VM heap allocated arguments descriptors.
@@ -53,7 +50,6 @@ class ScopedIsolateStackLimits : public ValueObject {
thread->SetStackLimit(Simulator::Current()->overflow_stack_limit());
#else
thread->SetStackLimit(OSThread::Current()->overflow_stack_limit());
// TODO(regis): For now, the interpreter is using its own stack limit.
#endif
#if defined(USING_SAFE_STACK)
@@ -135,27 +131,6 @@ ObjectPtr DartEntry::InvokeFunction(const Function& function,
ScopedIsolateStackLimits stack_limit(thread, current_sp);
#if !defined(DART_PRECOMPILED_RUNTIME)
if (!function.HasCode()) {
if (FLAG_enable_interpreter && function.IsBytecodeAllowed(zone)) {
if (!function.HasBytecode()) {
ErrorPtr error =
kernel::BytecodeReader::ReadFunctionBytecode(thread, function);
if (error != Error::null()) {
return error;
}
}
// If we have bytecode but no native code then invoke the interpreter.
if (function.HasBytecode() && (FLAG_compilation_counter_threshold != 0)) {
ASSERT(thread->no_callback_scope_depth() == 0);
SuspendLongJumpScope suspend_long_jump_scope(thread);
TransitionToGenerated transition(thread);
return Interpreter::Current()->Call(function, arguments_descriptor,
arguments, thread);
}
// Fall back to compilation.
}
const Object& result =
Object::Handle(zone, Compiler::CompileFunction(thread, function));
if (result.IsError()) {
-2
View File
@@ -174,8 +174,6 @@ class ArgumentsDescriptor : public ValueObject {
friend class SnapshotWriter;
friend class Serializer;
friend class Deserializer;
friend class Interpreter;
friend class InterpreterHelpers;
friend class Simulator;
friend class SimulatorHelpers;
DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor);
+320 -1128
View File
File diff suppressed because it is too large Load Diff
+8 -70
View File
@@ -7,7 +7,6 @@
#include "include/dart_tools_api.h"
#include "vm/constants_kbc.h"
#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/port.h"
@@ -152,21 +151,13 @@ class BreakpointLocation {
bool for_over_await);
bool AnyEnabled() const;
bool IsResolved() const {
return bytecode_token_pos_.IsReal() || code_token_pos_.IsReal();
}
bool IsResolved(bool in_bytecode) const {
return in_bytecode ? bytecode_token_pos_.IsReal()
: code_token_pos_.IsReal();
}
bool IsResolved() const { return code_token_pos_.IsReal(); }
bool IsLatent() const { return !token_pos_.IsReal(); }
private:
void VisitObjectPointers(ObjectPointerVisitor* visitor);
void SetResolved(bool in_bytecode,
const Function& func,
TokenPosition token_pos);
void SetResolved(const Function& func, TokenPosition token_pos);
BreakpointLocation* next() const { return this->next_; }
void set_next(BreakpointLocation* value) { next_ = value; }
@@ -187,14 +178,13 @@ class BreakpointLocation {
// Valid for resolved breakpoints:
FunctionPtr function_;
TokenPosition bytecode_token_pos_;
TokenPosition code_token_pos_;
friend class Debugger;
DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
};
// CodeBreakpoint represents a location in compiled or interpreted code.
// CodeBreakpoint represents a location in compiled code.
// There may be more than one CodeBreakpoint for one BreakpointLocation,
// e.g. when a function gets compiled as a regular function and as a closure.
class CodeBreakpoint {
@@ -203,7 +193,6 @@ class CodeBreakpoint {
TokenPosition token_pos,
uword pc,
PcDescriptorsLayout::Kind kind);
CodeBreakpoint(const Bytecode& bytecode, TokenPosition token_pos, uword pc);
~CodeBreakpoint();
FunctionPtr function() const;
@@ -217,7 +206,6 @@ class CodeBreakpoint {
void Enable();
void Disable();
bool IsEnabled() const { return is_enabled_; }
bool IsInterpreted() const { return bytecode_ != Bytecode::null(); }
CodePtr OrigStubAddress() const;
@@ -232,11 +220,8 @@ class CodeBreakpoint {
void PatchCode();
void RestoreCode();
void SetBytecodeBreakpoint();
void UnsetBytecodeBreakpoint();
CodePtr code_;
BytecodePtr bytecode_;
TokenPosition token_pos_;
uword pc_;
intptr_t line_number_;
@@ -273,16 +258,6 @@ class ActivationFrame : public ZoneAllocated {
ActivationFrame(uword pc, const Code& code);
#if !defined(DART_PRECOMPILED_RUNTIME)
ActivationFrame(uword pc,
uword fp,
uword sp,
const Bytecode& bytecode,
Kind kind = kRegular);
ActivationFrame(uword pc, const Bytecode& bytecode);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
explicit ActivationFrame(Kind kind);
explicit ActivationFrame(const Closure& async_activation);
@@ -291,11 +266,7 @@ class ActivationFrame : public ZoneAllocated {
uword fp() const { return fp_; }
uword sp() const { return sp_; }
uword GetCallerSp() const {
return fp() +
((IsInterpreted() ? kKBCCallerSpSlotFromFp : kCallerSpSlotFromFp) *
kWordSize);
}
uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }
const Function& function() const {
return function_;
@@ -304,11 +275,6 @@ class ActivationFrame : public ZoneAllocated {
ASSERT(!code_.IsNull());
return code_;
}
const Bytecode& bytecode() const {
ASSERT(!bytecode_.IsNull());
return bytecode_;
}
bool IsInterpreted() const { return !bytecode_.IsNull(); }
enum Relation {
kCallee,
@@ -316,7 +282,7 @@ class ActivationFrame : public ZoneAllocated {
kCaller,
};
Relation CompareTo(uword other_fp, bool other_is_interpreted) const;
Relation CompareTo(uword other_fp) const;
StringPtr QualifiedFunctionName();
StringPtr SourceUrl();
@@ -430,7 +396,6 @@ class ActivationFrame : public ZoneAllocated {
// The anchor of the context chain for this function.
Context& ctx_;
Code& code_;
Bytecode& bytecode_;
Function& function_;
bool live_frame_; // Is this frame a live frame?
bool token_pos_initialized_;
@@ -473,7 +438,6 @@ class DebuggerStackTrace : public ZoneAllocated {
void AddActivation(ActivationFrame* frame);
void AddMarker(ActivationFrame::Kind marker);
void AddAsyncCausalFrame(uword pc, const Code& code);
void AddAsyncCausalFrame(uword pc, const Bytecode& bytecode);
ZoneGrowableArray<ActivationFrame*> trace_;
@@ -508,12 +472,7 @@ class Debugger {
void OnIsolateRunnable();
void NotifyCompilation(const Function& func) {
HandleCodeChange(/* bytecode_loaded = */ false, func);
}
void NotifyBytecodeLoaded(const Function& func) {
HandleCodeChange(/* bytecode_loaded = */ true, func);
}
void NotifyCompilation(const Function& func);
void NotifyDoneLoading();
// Set breakpoint at closest location to function entry.
@@ -561,10 +520,6 @@ class Debugger {
ignore_breakpoints_ = ignore_breakpoints;
}
bool HasEnabledBytecodeBreakpoints() const;
// Called from the interpreter. Note that pc already points to next bytecode.
bool HasBytecodeBreakpointAt(const KBCInstr* next_pc) const;
// Put the isolate into single stepping mode when Dart code next runs.
//
// This is used by the vm service to allow the user to step while
@@ -588,7 +543,6 @@ class Debugger {
// debugger's zone.
bool HasBreakpoint(const Function& func, Zone* zone);
bool HasBreakpoint(const Code& code);
// A Bytecode version of HasBreakpoint is not needed.
// Returns true if the call at address pc is patched to point to
// a debugger stub.
@@ -669,7 +623,6 @@ class Debugger {
void FindCompiledFunctions(const Script& script,
TokenPosition start_pos,
TokenPosition end_pos,
GrowableObjectArray* bytecode_function_list,
GrowableObjectArray* code_function_list);
bool FindBestFit(const Script& script,
TokenPosition token_pos,
@@ -677,17 +630,14 @@ class Debugger {
Function* best_fit);
FunctionPtr FindInnermostClosure(const Function& function,
TokenPosition token_pos);
TokenPosition ResolveBreakpointPos(bool in_bytecode,
const Function& func,
TokenPosition ResolveBreakpointPos(const Function& func,
TokenPosition requested_token_pos,
TokenPosition last_token_pos,
intptr_t requested_column,
TokenPosition exact_token_pos);
void DeoptimizeWorld();
void NotifySingleStepping(bool value) const;
BreakpointLocation* SetCodeBreakpoints(bool in_bytecode,
BreakpointLocation* loc,
const Script& script,
BreakpointLocation* SetCodeBreakpoints(const Script& script,
TokenPosition token_pos,
TokenPosition last_token_pos,
intptr_t requested_line,
@@ -714,7 +664,6 @@ class Debugger {
TokenPosition token_pos,
intptr_t requested_line,
intptr_t requested_column,
TokenPosition bytecode_token_pos = TokenPosition::kNoSource,
TokenPosition code_token_pos = TokenPosition::kNoSource);
void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
// Returns NULL if no breakpoint exists for the given address.
@@ -724,8 +673,6 @@ class Debugger {
void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
JSONArray* jsarr) const;
void HandleCodeChange(bool bytecode_loaded, const Function& func);
ActivationFrame* TopDartFrame() const;
static ActivationFrame* CollectDartFrame(
Isolate* isolate,
@@ -736,12 +683,6 @@ class Debugger {
intptr_t deopt_frame_offset,
ActivationFrame::Kind kind = ActivationFrame::kRegular);
#if !defined(DART_PRECOMPILED_RUNTIME)
static ActivationFrame* CollectDartFrame(
Isolate* isolate,
uword pc,
StackFrame* frame,
const Bytecode& bytecode,
ActivationFrame::Kind kind = ActivationFrame::kRegular);
static ArrayPtr DeoptimizeToArray(Thread* thread,
StackFrame* frame,
const Code& code);
@@ -789,7 +730,6 @@ class Debugger {
void RewindToOptimizedFrame(StackFrame* frame,
const Code& code,
intptr_t post_deopt_frame_index);
void RewindToInterpretedFrame(StackFrame* frame, const Bytecode& bytecode);
void ResetSteppingFramePointers();
bool SteppedForSyntheticAsyncBreakpoint() const;
@@ -832,7 +772,6 @@ class Debugger {
// frame corresponds to this fp value, or if the top frame is
// lower on the stack.
uword stepping_fp_;
bool interpreted_stepping_;
// When stepping through code, do not stop more than once in the same
// token position range.
@@ -841,7 +780,6 @@ class Debugger {
// Used to track the current async/async* function.
uword async_stepping_fp_;
bool interpreted_async_stepping_;
ObjectPtr top_frame_awaiter_;
// If we step while at a breakpoint, we would hit the same pc twice.
-56
View File
@@ -1,56 +0,0 @@
// Copyright (c) 2019, 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/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/debugger.h"
#include "vm/instructions_kbc.h"
#include "vm/interpreter.h"
namespace dart {
#ifndef PRODUCT
void CodeBreakpoint::SetBytecodeBreakpoint() {
ASSERT(!is_enabled_);
is_enabled_ = true;
Interpreter::Current()->set_is_debugging(true);
}
void CodeBreakpoint::UnsetBytecodeBreakpoint() {
ASSERT(is_enabled_);
is_enabled_ = false;
if (!Isolate::Current()->single_step() &&
!Isolate::Current()->debugger()->HasEnabledBytecodeBreakpoints()) {
Interpreter::Current()->set_is_debugging(false);
}
}
bool Debugger::HasEnabledBytecodeBreakpoints() const {
CodeBreakpoint* cbpt = code_breakpoints_;
while (cbpt != nullptr) {
if (cbpt->IsEnabled() && cbpt->IsInterpreted()) {
return true;
}
cbpt = cbpt->next();
}
return false;
}
bool Debugger::HasBytecodeBreakpointAt(const KBCInstr* next_pc) const {
CodeBreakpoint* cbpt = code_breakpoints_;
while (cbpt != nullptr) {
if ((reinterpret_cast<uword>(next_pc)) == cbpt->pc_ && cbpt->IsEnabled()) {
ASSERT(cbpt->IsInterpreted());
return true;
}
cbpt = cbpt->next();
}
return false;
}
#endif // !PRODUCT
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-1
View File
@@ -378,7 +378,6 @@ intptr_t DeoptContext::MaterializeDeferredObjects() {
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* top_frame = iterator.NextFrame();
ASSERT(top_frame != NULL);
ASSERT(!top_frame->is_interpreted());
const Code& code = Code::Handle(top_frame->LookupDartCode());
const Function& top_function = Function::Handle(code.function());
const Script& script = Script::Handle(top_function.script());
+5 -31
View File
@@ -24,7 +24,6 @@
namespace dart {
DECLARE_FLAG(bool, enable_interpreter);
DECLARE_FLAG(bool, trace_deoptimization);
DEFINE_FLAG(bool,
print_stacktrace_at_throw,
@@ -129,26 +128,15 @@ static void BuildStackTrace(StackTraceBuilder* builder) {
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL); // We expect to find a dart invocation frame.
Code& code = Code::Handle();
Bytecode& bytecode = Bytecode::Handle();
Smi& offset = Smi::Handle();
for (; frame != NULL; frame = frames.NextFrame()) {
if (!frame->IsDartFrame()) {
continue;
}
if (frame->is_interpreted()) {
bytecode = frame->LookupDartBytecode();
ASSERT(bytecode.ContainsInstructionAt(frame->pc()));
if (bytecode.function() == Function::null()) {
continue;
}
offset = Smi::New(frame->pc() - bytecode.PayloadStart());
builder->AddFrame(bytecode, offset);
} else {
code = frame->LookupDartCode();
ASSERT(code.ContainsInstructionAt(frame->pc()));
offset = Smi::New(frame->pc() - code.PayloadStart());
builder->AddFrame(code, offset);
}
code = frame->LookupDartCode();
ASSERT(code.ContainsInstructionAt(frame->pc()));
offset = Smi::New(frame->pc() - code.PayloadStart());
builder->AddFrame(code, offset);
}
}
@@ -622,9 +610,7 @@ static void ClearLazyDeopts(Thread* thread, uword frame_pointer) {
StackFrameIterator::kNoCrossThreadIteration);
for (StackFrame* frame = frames.NextFrame(); frame != nullptr;
frame = frames.NextFrame()) {
if (frame->is_interpreted()) {
continue;
} else if (frame->fp() >= frame_pointer) {
if (frame->fp() >= frame_pointer) {
break;
}
if (frame->IsMarkedForLazyDeopt()) {
@@ -677,18 +663,6 @@ void Exceptions::JumpToFrame(Thread* thread,
uword stack_pointer,
uword frame_pointer,
bool clear_deopt_at_target) {
#if !defined(DART_PRECOMPILED_RUNTIME)
// TODO(regis): We still possibly need to unwind interpreter frames if they
// are callee frames of the C++ frame handling the exception.
if (FLAG_enable_interpreter) {
Interpreter* interpreter = thread->interpreter();
if ((interpreter != NULL) && interpreter->HasFrame(frame_pointer)) {
interpreter->JumpToFrame(program_counter, stack_pointer, frame_pointer,
thread);
}
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
const uword fp_for_clearing =
(clear_deopt_at_target ? frame_pointer + 1 : frame_pointer);
ClearLazyDeopts(thread, fp_for_clearing);
-5
View File
@@ -96,9 +96,6 @@ constexpr bool kDartUseBackgroundCompilation = true;
"Collects all dynamic function names to identify unique targets") \
P(compactor_tasks, int, 2, \
"The number of tasks to use for parallel compaction.") \
P(compilation_counter_threshold, int, 10, \
"Function's usage-counter value before interpreted function is compiled, " \
"-1 means never") \
P(concurrent_mark, bool, true, "Concurrent mark for old generation.") \
P(concurrent_sweep, bool, true, "Concurrent sweep for old generation.") \
C(deoptimize_alot, false, false, bool, false, \
@@ -219,7 +216,6 @@ constexpr bool kDartUseBackgroundCompilation = true;
D(trace_zones, bool, false, "Traces allocation sizes in the zone.") \
P(truncating_left_shift, bool, true, \
"Optimize left shift to truncate if possible") \
P(use_bytecode_compiler, bool, false, "Compile from bytecode") \
P(use_compactor, bool, false, "Compact the heap during old-space GC.") \
P(use_cha_deopt, bool, true, \
"Use class hierarchy analysis even if it can cause deoptimization.") \
@@ -242,7 +238,6 @@ constexpr bool kDartUseBackgroundCompilation = true;
"Enable magical pragmas for testing purposes. Use at your own risk!") \
R(eliminate_type_checks, true, bool, true, \
"Eliminate type checks when allowed by static type analysis.") \
P(enable_interpreter, bool, false, "Enable interpreting kernel bytecode.") \
D(support_rr, bool, false, "Support running within RR.") \
P(verify_entry_points, bool, false, \
"Throw API error on invalid member access throuh native API. See " \
-20
View File
@@ -53,26 +53,6 @@ void _printGeneratedStackTrace(uword fp, uword sp, uword pc) {
}
}
// Like _printDartStackTrace, but works in the interpreter loop.
// Must be called with the current interpreter fp, sp, and pc.
// Note that sp[0] is not modified, but sp[1] will be trashed.
DART_EXPORT
void _printInterpreterStackTrace(ObjectPtr* fp,
ObjectPtr* sp,
const KBCInstr* pc) {
Thread* thread = Thread::Current();
sp[1] = Function::null();
sp[2] = Bytecode::null();
sp[3] = static_cast<ObjectPtr>(reinterpret_cast<uword>(pc));
sp[4] = static_cast<ObjectPtr>(reinterpret_cast<uword>(fp));
ObjectPtr* exit_fp = sp + 1 + kKBCDartFrameFixedSize;
thread->set_top_exit_frame_info(reinterpret_cast<uword>(exit_fp));
thread->set_execution_state(Thread::kThreadInVM);
_printDartStackTrace();
thread->set_execution_state(Thread::kThreadInGenerated);
thread->set_top_exit_frame_info(0);
}
class PrintObjectPointersVisitor : public ObjectPointerVisitor {
public:
PrintObjectPointersVisitor()
-14
View File
@@ -312,20 +312,6 @@ class MarkingWeakVisitor : public HandleVisitor {
void GCMarker::Prologue() {
isolate_group_->ReleaseStoreBuffers();
#ifndef DART_PRECOMPILED_RUNTIME
isolate_group_->ForEachIsolate(
[&](Isolate* isolate) {
Thread* mutator_thread = isolate->mutator_thread();
if (mutator_thread != NULL) {
Interpreter* interpreter = mutator_thread->interpreter();
if (interpreter != NULL) {
interpreter->ClearLookupCache();
}
}
},
/*at_safepoint=*/true);
#endif
}
void GCMarker::Epilogue() {}
+4 -6
View File
@@ -76,12 +76,10 @@ void WeakCodeReferences::DisableCode() {
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = iterator.NextFrame();
while (frame != NULL) {
if (!frame->is_interpreted()) {
code = frame->LookupDartCode();
if (IsOptimizedCode(code_objects, code)) {
ReportDeoptimization(code);
DeoptimizeAt(code, frame);
}
code = frame->LookupDartCode();
if (IsOptimizedCode(code_objects, code)) {
ReportDeoptimization(code);
DeoptimizeAt(code, frame);
}
frame = iterator.NextFrame();
}
-47
View File
@@ -1,47 +0,0 @@
// Copyright (c) 2018, 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/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/instructions.h"
#include "vm/instructions_kbc.h"
#include "vm/constants_kbc.h"
#include "vm/native_entry.h"
namespace dart {
TypedDataPtr KBCNativeCallPattern::GetNativeEntryDataAt(
uword pc,
const Bytecode& bytecode) {
ASSERT(bytecode.ContainsInstructionAt(pc));
const KBCInstr* return_addr = reinterpret_cast<const KBCInstr*>(pc);
const KBCInstr* instr =
reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart());
ASSERT(instr < return_addr);
while (!KernelBytecode::IsNativeCallOpcode(instr)) {
instr = KernelBytecode::Next(instr);
if (instr >= return_addr) {
FATAL1(
"Unable to find NativeCall bytecode instruction"
" corresponding to PC %" Px,
pc);
}
}
intptr_t native_entry_data_pool_index = KernelBytecode::DecodeD(instr);
const ObjectPool& obj_pool = ObjectPool::Handle(bytecode.object_pool());
TypedData& native_entry_data = TypedData::Handle();
native_entry_data ^= obj_pool.ObjectAt(native_entry_data_pool_index);
// Native calls to recognized functions should never be patched.
ASSERT(NativeEntryData(native_entry_data).kind() ==
MethodRecognizer::kUnknown);
return native_entry_data.raw();
}
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-25
View File
@@ -1,25 +0,0 @@
// Copyright (c) 2018, 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.
// Classes that describe assembly patterns as used by inline caches.
#ifndef RUNTIME_VM_INSTRUCTIONS_KBC_H_
#define RUNTIME_VM_INSTRUCTIONS_KBC_H_
#include "vm/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/object.h"
namespace dart {
class KBCNativeCallPattern : public AllStatic {
public:
static TypedDataPtr GetNativeEntryDataAt(uword pc, const Bytecode& bytecode);
};
#endif // !defined(DART_PRECOMPILED_RUNTIME)
} // namespace dart
#endif // RUNTIME_VM_INSTRUCTIONS_KBC_H_
File diff suppressed because it is too large Load Diff
-281
View File
@@ -1,281 +0,0 @@
// Copyright (c) 2018, 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_INTERPRETER_H_
#define RUNTIME_VM_INTERPRETER_H_
#include "vm/globals.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/method_recognizer.h"
#include "vm/constants_kbc.h"
#include "vm/tagged_pointer.h"
namespace dart {
class Array;
class Code;
class InterpreterSetjmpBuffer;
class Isolate;
class ObjectPointerVisitor;
class Thread;
class LookupCache : public ValueObject {
public:
LookupCache() {
ASSERT(Utils::IsPowerOfTwo(sizeof(Entry)));
ASSERT(Utils::IsPowerOfTwo(sizeof(kNumEntries)));
Clear();
}
void Clear();
bool Lookup(intptr_t receiver_cid,
StringPtr function_name,
ArrayPtr arguments_descriptor,
FunctionPtr* target) const;
void Insert(intptr_t receiver_cid,
StringPtr function_name,
ArrayPtr arguments_descriptor,
FunctionPtr target);
private:
struct Entry {
intptr_t receiver_cid;
StringPtr function_name;
ArrayPtr arguments_descriptor;
FunctionPtr target;
};
static const intptr_t kNumEntries = 1024;
static const intptr_t kTableMask = kNumEntries - 1;
Entry entries_[kNumEntries];
};
// Interpreter intrinsic handler. It is invoked on entry to the intrinsified
// function via Intrinsic bytecode before the frame is setup.
// If the handler returns true then Intrinsic bytecode works as a return
// instruction returning the value in result. Otherwise interpreter proceeds to
// execute the body of the function.
typedef bool (*IntrinsicHandler)(Thread* thread,
ObjectPtr* FP,
ObjectPtr* result);
class Interpreter {
public:
static const uword kInterpreterStackUnderflowSize = 0x80;
// The entry frame pc marker must be non-zero (a valid exception handler pc).
static const word kEntryFramePcMarker = -1;
Interpreter();
~Interpreter();
// The currently executing Interpreter instance, which is associated to the
// current isolate
static Interpreter* Current();
// Low address (KBC stack grows up).
uword stack_base() const { return stack_base_; }
// Limit for StackOverflowError.
uword overflow_stack_limit() const { return overflow_stack_limit_; }
// High address (KBC stack grows up).
uword stack_limit() const { return stack_limit_; }
// Returns true if the interpreter's stack contains the given frame.
// TODO(regis): We should rely on a new thread vm_tag to identify an
// interpreter frame and not need this HasFrame() method.
bool HasFrame(uword frame) const {
return frame >= stack_base() && frame < stack_limit();
}
// Identify an entry frame by looking at its pc marker value.
static bool IsEntryFrameMarker(const KBCInstr* pc) {
return reinterpret_cast<word>(pc) == kEntryFramePcMarker;
}
ObjectPtr Call(const Function& function,
const Array& arguments_descriptor,
const Array& arguments,
Thread* thread);
ObjectPtr Call(FunctionPtr function,
ArrayPtr argdesc,
intptr_t argc,
ObjectPtr const* argv,
Thread* thread);
void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
uword get_sp() const { return reinterpret_cast<uword>(fp_); } // Yes, fp_.
uword get_fp() const { return reinterpret_cast<uword>(fp_); }
uword get_pc() const { return reinterpret_cast<uword>(pc_); }
void Unexit(Thread* thread);
void VisitObjectPointers(ObjectPointerVisitor* visitor);
void ClearLookupCache() { lookup_cache_.Clear(); }
#ifndef PRODUCT
void set_is_debugging(bool value) { is_debugging_ = value; }
bool is_debugging() const { return is_debugging_; }
#endif // !PRODUCT
private:
uintptr_t* stack_;
uword stack_base_;
uword overflow_stack_limit_;
uword stack_limit_;
ObjectPtr* volatile fp_;
const KBCInstr* volatile pc_;
DEBUG_ONLY(uint64_t icount_;)
InterpreterSetjmpBuffer* last_setjmp_buffer_;
ObjectPoolPtr pp_; // Pool Pointer.
ArrayPtr argdesc_; // Arguments Descriptor: used to pass information between
// call instruction and the function entry.
ObjectPtr special_[KernelBytecode::kSpecialIndexCount];
LookupCache lookup_cache_;
void Exit(Thread* thread,
ObjectPtr* base,
ObjectPtr* exit_frame,
const KBCInstr* pc);
bool Invoke(Thread* thread,
ObjectPtr* call_base,
ObjectPtr* call_top,
const KBCInstr** pc,
ObjectPtr** FP,
ObjectPtr** SP);
bool InvokeCompiled(Thread* thread,
FunctionPtr function,
ObjectPtr* call_base,
ObjectPtr* call_top,
const KBCInstr** pc,
ObjectPtr** FP,
ObjectPtr** SP);
bool InvokeBytecode(Thread* thread,
FunctionPtr function,
ObjectPtr* call_base,
ObjectPtr* call_top,
const KBCInstr** pc,
ObjectPtr** FP,
ObjectPtr** SP);
bool InstanceCall(Thread* thread,
StringPtr target_name,
ObjectPtr* call_base,
ObjectPtr* call_top,
const KBCInstr** pc,
ObjectPtr** FP,
ObjectPtr** SP);
bool CopyParameters(Thread* thread,
const KBCInstr** pc,
ObjectPtr** FP,
ObjectPtr** SP,
const intptr_t num_fixed_params,
const intptr_t num_opt_pos_params,
const intptr_t num_opt_named_params);
bool AssertAssignable(Thread* thread,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* call_top,
ObjectPtr* args,
SubtypeTestCachePtr cache);
template <bool is_getter>
bool AssertAssignableField(Thread* thread,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP,
InstancePtr instance,
FieldPtr field,
InstancePtr value);
bool AllocateMint(Thread* thread,
int64_t value,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateDouble(Thread* thread,
double value,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateFloat32x4(Thread* thread,
simd128_value_t value,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateFloat64x2(Thread* thread,
simd128_value_t value,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateArray(Thread* thread,
TypeArgumentsPtr type_args,
ObjectPtr length,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateContext(Thread* thread,
intptr_t num_variables,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
bool AllocateClosure(Thread* thread,
const KBCInstr* pc,
ObjectPtr* FP,
ObjectPtr* SP);
#if defined(DEBUG)
// Returns true if tracing of executed instructions is enabled.
bool IsTracingExecution() const;
// Prints bytecode instruction at given pc for instruction tracing.
void TraceInstruction(const KBCInstr* pc) const;
bool IsWritingTraceFile() const;
void FlushTraceBuffer();
void WriteInstructionToTrace(const KBCInstr* pc);
void* trace_file_;
uint64_t trace_file_bytes_written_;
static const intptr_t kTraceBufferSizeInBytes = 10 * KB;
static const intptr_t kTraceBufferInstrs =
kTraceBufferSizeInBytes / sizeof(KBCInstr);
KBCInstr* trace_buffer_;
intptr_t trace_buffer_idx_;
#endif // defined(DEBUG)
// Longjmp support for exceptions.
InterpreterSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
void set_last_setjmp_buffer(InterpreterSetjmpBuffer* buffer) {
last_setjmp_buffer_ = buffer;
}
#ifndef PRODUCT
bool is_debugging_ = false;
#endif // !PRODUCT
bool supports_unboxed_doubles_;
bool supports_unboxed_simd128_;
friend class InterpreterSetjmpBuffer;
DISALLOW_COPY_AND_ASSIGN(Interpreter);
};
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_INTERPRETER_H_
-14
View File
@@ -26,7 +26,6 @@
#include "vm/heap/safepoint.h"
#include "vm/heap/verifier.h"
#include "vm/image_snapshot.h"
#include "vm/interpreter.h"
#include "vm/isolate_reload.h"
#include "vm/kernel_isolate.h"
#include "vm/lockers.h"
@@ -1681,10 +1680,6 @@ Isolate::Isolate(IsolateGroup* isolate_group,
" See dartbug.com/30524 for more information.\n");
}
if (FLAG_enable_interpreter) {
NOT_IN_PRECOMPILED(background_compiler_ = new BackgroundCompiler(
this, /* optimizing = */ false));
}
NOT_IN_PRECOMPILED(optimizing_background_compiler_ =
new BackgroundCompiler(this, /* optimizing = */ true));
}
@@ -1698,11 +1693,6 @@ Isolate::~Isolate() {
// RELEASE_ASSERT(reload_context_ == NULL);
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_enable_interpreter) {
delete background_compiler_;
background_compiler_ = nullptr;
}
delete optimizing_background_compiler_;
optimizing_background_compiler_ = nullptr;
@@ -2602,10 +2592,6 @@ void Isolate::set_forward_table_old(WeakTable* table) {
void Isolate::Shutdown() {
ASSERT(this == Isolate::Current());
BackgroundCompiler::Stop(this);
if (FLAG_enable_interpreter) {
delete background_compiler_;
background_compiler_ = nullptr;
}
delete optimizing_background_compiler_;
optimizing_background_compiler_ = nullptr;
-4
View File
@@ -18,7 +18,6 @@
#include "platform/atomic.h"
#include "vm/base_isolate.h"
#include "vm/class_table.h"
#include "vm/constants_kbc.h"
#include "vm/dispatch_table.h"
#include "vm/exceptions.h"
#include "vm/field_table.h"
@@ -56,9 +55,6 @@ class HandleScope;
class HandleVisitor;
class Heap;
class ICData;
#if !defined(DART_PRECOMPILED_RUNTIME)
class Interpreter;
#endif
class IsolateObjectStore;
class IsolateProfilerData;
class IsolateReloadContext;
+13 -37
View File
@@ -1221,7 +1221,7 @@ void IsolateReloadContext::EnsuredUnoptimizedCodeForStack() {
Function& func = Function::Handle();
while (it.HasNextFrame()) {
StackFrame* frame = it.NextFrame();
if (frame->IsDartFrame() && !frame->is_interpreted()) {
if (frame->IsDartFrame()) {
func = frame->LookupDartFunction();
ASSERT(!func.IsNull());
// Force-optimized functions don't need unoptimized code because their
@@ -1945,31 +1945,25 @@ void IsolateReloadContext::ResetUnoptimizedICsOnStack() {
Zone* zone = stack_zone.GetZone();
Code& code = Code::Handle(zone);
Bytecode& bytecode = Bytecode::Handle(zone);
Function& function = Function::Handle(zone);
CallSiteResetter resetter(zone);
DartFrameIterator iterator(thread,
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = iterator.NextFrame();
while (frame != NULL) {
if (frame->is_interpreted()) {
bytecode = frame->LookupDartBytecode();
resetter.RebindStaticTargets(bytecode);
code = frame->LookupDartCode();
if (code.is_optimized() && !code.is_force_optimized()) {
// If this code is optimized, we need to reset the ICs in the
// corresponding unoptimized code, which will be executed when the stack
// unwinds to the optimized code.
function = code.function();
code = function.unoptimized_code();
ASSERT(!code.IsNull());
resetter.ResetSwitchableCalls(code);
resetter.ResetCaches(code);
} else {
code = frame->LookupDartCode();
if (code.is_optimized() && !code.is_force_optimized()) {
// If this code is optimized, we need to reset the ICs in the
// corresponding unoptimized code, which will be executed when the stack
// unwinds to the optimized code.
function = code.function();
code = function.unoptimized_code();
ASSERT(!code.IsNull());
resetter.ResetSwitchableCalls(code);
resetter.ResetCaches(code);
} else {
resetter.ResetSwitchableCalls(code);
resetter.ResetCaches(code);
}
resetter.ResetSwitchableCalls(code);
resetter.ResetCaches(code);
}
frame = iterator.NextFrame();
}
@@ -2032,14 +2026,6 @@ void IsolateReloadContext::RunInvalidationVisitors() {
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
Thread* mutator_thread = I->mutator_thread();
if (mutator_thread != nullptr) {
Interpreter* interpreter = mutator_thread->interpreter();
if (interpreter != nullptr) {
interpreter->ClearLookupCache();
}
}
GrowableArray<const Function*> functions(4 * KB);
GrowableArray<const KernelProgramInfo*> kernel_infos(KB);
GrowableArray<const Field*> fields(4 * KB);
@@ -2084,10 +2070,6 @@ void IsolateReloadContext::InvalidateKernelInfos(
table.Clear();
info.set_classes_cache(table.Release());
}
// Clear the bytecode object table.
if (info.bytecode_component() != Array::null()) {
kernel::BytecodeReader::ResetObjectTable(info);
}
}
}
@@ -2102,7 +2084,6 @@ void IsolateReloadContext::InvalidateFunctions(
Class& owning_class = Class::Handle(zone);
Library& owning_lib = Library::Handle(zone);
Code& code = Code::Handle(zone);
Bytecode& bytecode = Bytecode::Handle(zone);
for (intptr_t i = 0; i < functions.length(); i++) {
const Function& func = *functions[i];
if (func.IsSignatureFunction()) {
@@ -2115,7 +2096,6 @@ void IsolateReloadContext::InvalidateFunctions(
// Grab the current code.
code = func.CurrentCode();
ASSERT(!code.IsNull());
bytecode = func.bytecode();
owning_class = func.Owner();
owning_lib = owning_class.library();
@@ -2126,10 +2106,6 @@ void IsolateReloadContext::InvalidateFunctions(
// they're held.
resetter.ZeroEdgeCounters(func);
if (!bytecode.IsNull()) {
resetter.RebindStaticTargets(bytecode);
}
if (stub_code) {
// Nothing to reset.
} else if (clear_code) {
-1
View File
@@ -435,7 +435,6 @@ class CallSiteResetter : public ValueObject {
void ZeroEdgeCounters(const Function& function);
void ResetCaches(const Code& code);
void ResetCaches(const ObjectPool& pool);
void RebindStaticTargets(const Bytecode& code);
void Reset(const ICData& ic);
void ResetSwitchableCalls(const Code& code);
+23 -200
View File
@@ -7,7 +7,6 @@
#include "vm/kernel.h"
#include "vm/bit_vector.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/compiler/jit/compiler.h"
@@ -230,71 +229,6 @@ static void CollectKernelDataTokenPositions(
token_position_collector.CollectTokenPositions(kernel_offset);
}
static void CollectTokenPosition(TokenPosition position,
GrowableArray<intptr_t>* token_positions) {
if (position.IsReal()) {
token_positions->Add(position.value());
}
}
static void CollectBytecodeSourceTokenPositions(
const Bytecode& bytecode,
Zone* zone,
GrowableArray<intptr_t>* token_positions) {
BytecodeSourcePositionsIterator iter(zone, bytecode);
while (iter.MoveNext()) {
CollectTokenPosition(iter.TokenPos(), token_positions);
}
}
static void CollectBytecodeFunctionTokenPositions(
const Function& function,
GrowableArray<intptr_t>* token_positions) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
ASSERT(function.is_declared_in_bytecode());
CollectTokenPosition(function.token_pos(), token_positions);
CollectTokenPosition(function.end_token_pos(), token_positions);
if (!function.HasBytecode()) {
const Object& result = Object::Handle(
zone, BytecodeReader::ReadFunctionBytecode(thread, function));
if (!result.IsNull()) {
Exceptions::PropagateError(Error::Cast(result));
}
}
Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
if (bytecode.IsNull()) {
return;
}
if (bytecode.HasSourcePositions() && !function.IsLocalFunction()) {
CollectBytecodeSourceTokenPositions(bytecode, zone, token_positions);
// Find closure functions in the object pool.
const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
Object& object = Object::Handle(zone);
Function& closure = Function::Handle(zone);
for (intptr_t i = 0; i < pool.Length(); i++) {
ObjectPool::EntryType entry_type = pool.TypeAt(i);
if (entry_type != ObjectPool::EntryType::kTaggedObject) {
continue;
}
object = pool.ObjectAt(i);
if (object.IsFunction()) {
closure ^= object.raw();
if (closure.kind() == FunctionLayout::kClosureFunction &&
closure.IsLocalFunction()) {
CollectTokenPosition(closure.token_pos(), token_positions);
CollectTokenPosition(closure.end_token_pos(), token_positions);
bytecode = closure.bytecode();
ASSERT(!bytecode.IsNull());
ASSERT(bytecode.function() != Function::null());
ASSERT(bytecode.HasSourcePositions());
CollectBytecodeSourceTokenPositions(bytecode, zone, token_positions);
}
}
}
}
}
void CollectTokenPositionsFor(const Script& interesting_script) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
@@ -328,22 +262,11 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
token_positions.Add(klass.token_pos().value());
token_positions.Add(klass.end_token_pos().value());
}
// If class is declared in bytecode, its members should be loaded
// (via class finalization) before their token positions could be
// collected.
if (klass.is_declared_in_bytecode() && !klass.is_finalized()) {
const Error& error =
Error::Handle(zone, klass.EnsureIsFinalized(thread));
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
}
if (klass.is_finalized()) {
temp_array = klass.fields();
for (intptr_t i = 0; i < temp_array.Length(); ++i) {
temp_field ^= temp_array.At(i);
if (!temp_field.is_declared_in_bytecode() &&
temp_field.kernel_offset() <= 0) {
if (temp_field.kernel_offset() <= 0) {
// Skip artificially injected fields.
continue;
}
@@ -351,23 +274,12 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
if (temp_field.is_declared_in_bytecode()) {
token_positions.Add(temp_field.token_pos().value());
token_positions.Add(temp_field.end_token_pos().value());
if (temp_field.is_static() &&
temp_field.has_nontrivial_initializer()) {
temp_function = temp_field.EnsureInitializerFunction();
CollectBytecodeFunctionTokenPositions(temp_function,
&token_positions);
}
} else {
data = temp_field.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script,
temp_field.kernel_offset(),
temp_field.KernelDataProgramOffset(), zone, &helper,
&token_positions);
}
data = temp_field.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script,
temp_field.kernel_offset(),
temp_field.KernelDataProgramOffset(), zone, &helper,
&token_positions);
}
temp_array = klass.current_functions();
for (intptr_t i = 0; i < temp_array.Length(); ++i) {
@@ -376,21 +288,15 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
if (temp_function.is_declared_in_bytecode()) {
CollectBytecodeFunctionTokenPositions(temp_function,
&token_positions);
} else {
data = temp_function.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script,
temp_function.kernel_offset(),
temp_function.KernelDataProgramOffset(), zone, &helper,
&token_positions);
}
data = temp_function.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script,
temp_function.kernel_offset(),
temp_function.KernelDataProgramOffset(), zone, &helper,
&token_positions);
}
} else {
// Class isn't finalized yet: read the data attached to it.
ASSERT(!klass.is_declared_in_bytecode());
ASSERT(klass.kernel_offset() > 0);
data = lib.kernel_data();
ASSERT(!data.IsNull());
@@ -412,20 +318,14 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
if (temp_function.is_declared_in_bytecode()) {
CollectBytecodeFunctionTokenPositions(temp_function,
&token_positions);
} else {
data = temp_function.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script,
temp_function.kernel_offset(),
temp_function.KernelDataProgramOffset(), zone, &helper,
&token_positions);
}
data = temp_function.KernelData();
CollectKernelDataTokenPositions(data, interesting_script, entry_script,
temp_function.kernel_offset(),
temp_function.KernelDataProgramOffset(),
zone, &helper, &token_positions);
} else if (entry.IsField()) {
const Field& field = Field::Cast(entry);
if (!field.is_declared_in_bytecode() && field.kernel_offset() <= 0) {
if (field.kernel_offset() <= 0) {
// Skip artificially injected fields.
continue;
}
@@ -433,20 +333,10 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
if (field.is_declared_in_bytecode()) {
token_positions.Add(field.token_pos().value());
token_positions.Add(field.end_token_pos().value());
if (field.is_static() && field.has_nontrivial_initializer()) {
temp_function = field.EnsureInitializerFunction();
CollectBytecodeFunctionTokenPositions(temp_function,
&token_positions);
}
} else {
data = field.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script, field.kernel_offset(),
field.KernelDataProgramOffset(), zone, &helper, &token_positions);
}
data = field.KernelData();
CollectKernelDataTokenPositions(
data, interesting_script, entry_script, field.kernel_offset(),
field.KernelDataProgramOffset(), zone, &helper, &token_positions);
}
}
}
@@ -627,15 +517,6 @@ ObjectPtr BuildParameterDescriptor(const Function& function) {
Script& script = Script::Handle(zone, function.script());
helper.InitFromScript(script);
if (function.is_declared_in_bytecode()) {
BytecodeComponentData bytecode_component(
&Array::Handle(zone, helper.GetBytecodeComponent()));
ActiveClass active_class;
BytecodeReaderHelper bytecode_reader_helper(&helper, &active_class,
&bytecode_component);
return bytecode_reader_helper.BuildParameterDescriptor(function);
}
const Class& owner_class = Class::Handle(zone, function.Owner());
ActiveClass active_class;
ActiveClassScope active_class_scope(&active_class, &owner_class);
@@ -665,14 +546,6 @@ void ReadParameterCovariance(const Function& function,
TranslationHelper translation_helper(thread);
translation_helper.InitFromScript(script);
if (function.is_declared_in_bytecode()) {
BytecodeReaderHelper bytecode_reader_helper(&translation_helper, nullptr,
nullptr);
bytecode_reader_helper.ReadParameterCovariance(function, is_covariant,
is_generic_covariant_impl);
return;
}
KernelReaderHelper reader_helper(
zone, &translation_helper, script,
ExternalTypedData::Handle(zone, function.KernelData()),
@@ -809,55 +682,8 @@ static ProcedureAttributesMetadata ProcedureAttributesOf(
return attrs;
}
static void BytecodeProcedureAttributesError(const Object& function_or_field,
const Object& value) {
FATAL3("Unexpected value of %s bytecode attribute on %s: %s",
Symbols::vm_procedure_attributes_metadata().ToCString(),
function_or_field.ToCString(), value.ToCString());
}
static ProcedureAttributesMetadata ProcedureAttributesFromBytecodeAttribute(
Zone* zone,
const Object& function_or_field) {
ProcedureAttributesMetadata attrs;
const Object& value = Object::Handle(
zone,
BytecodeReader::GetBytecodeAttribute(
function_or_field, Symbols::vm_procedure_attributes_metadata()));
if (!value.IsNull()) {
const intptr_t kBytecodeAttributeLength = 3;
int32_t elements[kBytecodeAttributeLength];
if (!value.IsArray()) {
BytecodeProcedureAttributesError(function_or_field, value);
}
const Array& array = Array::Cast(value);
if (array.Length() != kBytecodeAttributeLength) {
BytecodeProcedureAttributesError(function_or_field, value);
}
Object& element = Object::Handle(zone);
for (intptr_t i = 0; i < kBytecodeAttributeLength; i++) {
element = array.At(i);
if (!element.IsSmi()) {
BytecodeProcedureAttributesError(function_or_field, value);
}
elements[i] = Smi::Cast(element).Value();
}
attrs.InitializeFromFlags(elements[0]);
attrs.method_or_setter_selector_id = elements[1];
attrs.getter_selector_id = elements[2];
}
return attrs;
}
ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
Zone* zone) {
if (function.is_declared_in_bytecode()) {
if (function.IsImplicitGetterOrSetter()) {
const Field& field = Field::Handle(zone, function.accessor_field());
return ProcedureAttributesFromBytecodeAttribute(zone, field);
}
return ProcedureAttributesFromBytecodeAttribute(zone, function);
}
const Script& script = Script::Handle(zone, function.script());
return ProcedureAttributesOf(
zone, script, ExternalTypedData::Handle(zone, function.KernelData()),
@@ -866,9 +692,6 @@ ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
Zone* zone) {
if (field.is_declared_in_bytecode()) {
return ProcedureAttributesFromBytecodeAttribute(zone, field);
}
const Class& parent = Class::Handle(zone, field.Owner());
const Script& script = Script::Handle(zone, parent.script());
return ProcedureAttributesOf(
-5
View File
@@ -214,11 +214,6 @@ void ReadParameterCovariance(const Function& function,
// as such function already checks all of its parameters.
bool NeedsDynamicInvocationForwarder(const Function& function);
// Returns a list of ParameterTypeChecks needed by a dynamic invocation
// forwarder that targets [function]. Indices in these checks correspond to
// bytecode frame indices.
ArrayPtr CollectDynamicInvocationChecks(const Function& function);
ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
Zone* zone);
+1 -13
View File
@@ -647,11 +647,6 @@ class KernelCompilationRequest : public ValueObject {
experimental_flags_object.value.as_array.values = experimental_flags_array;
experimental_flags_object.value.as_array.length = num_experimental_flags;
Dart_CObject bytecode;
bytecode.type = Dart_CObject_kBool;
bytecode.value.as_bool =
FLAG_enable_interpreter || FLAG_use_bytecode_compiler;
Dart_CObject message;
message.type = Dart_CObject_kArray;
Dart_CObject* message_arr[] = {&tag,
@@ -668,8 +663,7 @@ class KernelCompilationRequest : public ValueObject {
&num_blob_loads,
&suppress_warnings,
&enable_asserts,
&experimental_flags_object,
&bytecode};
&experimental_flags_object};
message.value.as_array.values = message_arr;
message.value.as_array.length = ARRAY_SIZE(message_arr);
@@ -813,11 +807,6 @@ class KernelCompilationRequest : public ValueObject {
experimental_flags_object.value.as_array.values = experimental_flags_array;
experimental_flags_object.value.as_array.length = num_experimental_flags;
Dart_CObject bytecode;
bytecode.type = Dart_CObject_kBool;
bytecode.value.as_bool =
FLAG_enable_interpreter || FLAG_use_bytecode_compiler;
Dart_CObject package_config_uri;
if (package_config != NULL) {
package_config_uri.type = Dart_CObject_kString;
@@ -875,7 +864,6 @@ class KernelCompilationRequest : public ValueObject {
&suppress_warnings,
&enable_asserts,
&experimental_flags_object,
&bytecode,
&package_config_uri,
&multiroot_filepaths_object,
&multiroot_scheme_object,
+57 -94
View File
@@ -210,7 +210,6 @@ KernelLoader::KernelLoader(Program* program,
&active_class_,
/* finalize= */ false),
inferred_type_metadata_helper_(&helper_, &constant_reader_),
bytecode_metadata_helper_(&helper_, &active_class_),
external_name_class_(Class::Handle(Z)),
external_name_field_(Field::Handle(Z)),
potential_natives_(GrowableObjectArray::Handle(Z)),
@@ -450,8 +449,6 @@ void KernelLoader::InitializeFields(UriToSourceTable* uri_to_source_table) {
script = LoadScriptAt(index, uri_to_source_table);
scripts.SetAt(index, script);
}
bytecode_metadata_helper_.ReadBytecodeComponent();
}
KernelLoader::KernelLoader(const Script& script,
@@ -478,7 +475,6 @@ KernelLoader::KernelLoader(const Script& script,
&active_class_,
/* finalize= */ false),
inferred_type_metadata_helper_(&helper_, &constant_reader_),
bytecode_metadata_helper_(&helper_, &active_class_),
external_name_class_(Class::Handle(Z)),
external_name_field_(Field::Handle(Z)),
potential_natives_(GrowableObjectArray::Handle(Z)),
@@ -653,64 +649,49 @@ void KernelLoader::LoadNativeExtensionLibraries() {
for (intptr_t i = 0; i < length; ++i) {
library ^= potential_extension_libraries.At(i);
if (library.is_declared_in_bytecode()) {
const auto& imports = Array::Handle(Z, library.imports());
auto& ns = Namespace::Handle(Z);
auto& importee = Library::Handle(Z);
for (intptr_t j = 0; j < imports.Length(); ++j) {
ns ^= imports.At(j);
if (ns.IsNull()) continue;
importee = ns.library();
uri_path = importee.url();
if (uri_path.StartsWith(Symbols::DartExtensionScheme())) {
LoadNativeExtension(library, uri_path);
helper_.SetOffset(library.kernel_offset());
LibraryHelper library_helper(&helper_, kernel_binary_version_);
library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
const intptr_t annotation_count = helper_.ReadListLength();
for (intptr_t j = 0; j < annotation_count; ++j) {
uri_path = String::null();
const intptr_t tag = helper_.PeekTag();
if (tag == kConstantExpression) {
helper_.ReadByte(); // Skip the tag.
helper_.ReadPosition(); // Skip fileOffset.
helper_.SkipDartType(); // Skip type.
// We have a candidate. Let's look if it's an instance of the
// ExternalName class.
const intptr_t constant_table_offset = helper_.ReadUInt();
if (constant_reader.IsInstanceConstant(constant_table_offset,
external_name_class_)) {
constant = constant_reader.ReadConstant(constant_table_offset);
ASSERT(constant.clazz() == external_name_class_.raw());
uri_path ^= constant.GetField(external_name_field_);
}
} else if (tag == kConstructorInvocation ||
tag == kConstConstructorInvocation) {
uri_path = DetectExternalNameCtor();
} else {
helper_.SkipExpression();
}
} else {
helper_.SetOffset(library.kernel_offset());
LibraryHelper library_helper(&helper_, kernel_binary_version_);
library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
if (uri_path.IsNull()) continue;
const intptr_t annotation_count = helper_.ReadListLength();
for (intptr_t j = 0; j < annotation_count; ++j) {
uri_path = String::null();
LoadNativeExtension(library, uri_path);
const intptr_t tag = helper_.PeekTag();
if (tag == kConstantExpression) {
helper_.ReadByte(); // Skip the tag.
helper_.ReadPosition(); // Skip fileOffset.
helper_.SkipDartType(); // Skip type.
// We have a candidate. Let's look if it's an instance of the
// ExternalName class.
const intptr_t constant_table_offset = helper_.ReadUInt();
if (constant_reader.IsInstanceConstant(constant_table_offset,
external_name_class_)) {
constant = constant_reader.ReadConstant(constant_table_offset);
ASSERT(constant.clazz() == external_name_class_.raw());
uri_path ^= constant.GetField(external_name_field_);
}
} else if (tag == kConstructorInvocation ||
tag == kConstConstructorInvocation) {
uri_path = DetectExternalNameCtor();
} else {
helper_.SkipExpression();
}
if (uri_path.IsNull()) continue;
LoadNativeExtension(library, uri_path);
// Create a dummy library and add it as an import to the current
// library. This allows later to discover and reload this native
// extension, e.g. when running from an app-jit snapshot.
// See Loader::ReloadNativeExtensions(...) which relies on
// Dart_GetImportsOfScheme('dart-ext').
const auto& native_library = Library::Handle(Library::New(uri_path));
library.AddImport(Namespace::Handle(Namespace::New(
native_library, Array::null_array(), Array::null_array())));
}
// Create a dummy library and add it as an import to the current
// library. This allows later to discover and reload this native
// extension, e.g. when running from an app-jit snapshot.
// See Loader::ReloadNativeExtensions(...) which relies on
// Dart_GetImportsOfScheme('dart-ext').
const auto& native_library = Library::Handle(Library::New(uri_path));
library.AddImport(Namespace::Handle(Namespace::New(
native_library, Array::null_array(), Array::null_array())));
}
}
}
@@ -745,12 +726,10 @@ ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
if (!bytecode_metadata_helper_.ReadLibraries()) {
// Note that `problemsAsJson` on Component is implicitly skipped.
const intptr_t length = program_->library_count();
for (intptr_t i = 0; i < length; i++) {
LoadLibrary(i);
}
// Note that `problemsAsJson` on Component is implicitly skipped.
const intptr_t length = program_->library_count();
for (intptr_t i = 0; i < length; i++) {
LoadLibrary(i);
}
// Finalize still pending classes if requested.
@@ -780,7 +759,7 @@ ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
return LookupLibrary(main_library);
}
return bytecode_metadata_helper_.GetMainLibrary();
return Library::null();
}
// Either class finalization failed or we caught a compile error.
@@ -791,10 +770,6 @@ ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
void KernelLoader::LoadLibrary(const Library& library) {
ASSERT(!library.Loaded());
bytecode_metadata_helper_.ReadLibrary(library);
if (library.Loaded()) {
return;
}
const auto& uri = String::Handle(Z, library.url());
const intptr_t num_libraries = program_->library_count();
for (intptr_t i = 0; i < num_libraries; ++i) {
@@ -840,13 +815,10 @@ ObjectPtr KernelLoader::LoadExpressionEvaluationFunction(
// Make the expression evaluation function have the right script,
// kernel data and parent.
const auto& eval_script = Script::Handle(Z, function.script());
auto& kernel_data = ExternalTypedData::Handle(Z);
intptr_t kernel_offset = -1;
if (!function.is_declared_in_bytecode()) {
ASSERT(!expression_evaluation_library_.IsNull());
kernel_data = expression_evaluation_library_.kernel_data();
kernel_offset = expression_evaluation_library_.kernel_offset();
}
ASSERT(!expression_evaluation_library_.IsNull());
auto& kernel_data = ExternalTypedData::Handle(
Z, expression_evaluation_library_.kernel_data());
intptr_t kernel_offset = expression_evaluation_library_.kernel_offset();
function.SetKernelDataAndScript(eval_script, kernel_data, kernel_offset);
function.set_owner(real_class);
@@ -924,10 +896,6 @@ void KernelLoader::walk_incremental_kernel(BitVector* modified_libs,
bool* is_empty_program,
intptr_t* p_num_classes,
intptr_t* p_num_procedures) {
if (bytecode_metadata_helper_.FindModifiedLibrariesForHotReload(
modified_libs, is_empty_program, p_num_classes, p_num_procedures)) {
return;
}
intptr_t length = program_->library_count();
*is_empty_program = *is_empty_program && (length == 0);
bool collect_library_stats =
@@ -1146,7 +1114,7 @@ LibraryPtr KernelLoader::LoadLibrary(intptr_t index) {
if (FLAG_enable_mirrors && annotation_count > 0) {
ASSERT(annotations_kernel_offset > 0);
library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource,
annotations_kernel_offset, 0);
annotations_kernel_offset);
}
if (register_class) {
@@ -1267,8 +1235,7 @@ void KernelLoader::FinishTopLevelClassLoading(
}
if ((FLAG_enable_mirrors || has_pragma_annotation) &&
annotation_count > 0) {
library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
0);
library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset);
}
fields_.Add(&field);
}
@@ -1533,7 +1500,7 @@ void KernelLoader::LoadClass(const Library& library,
if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) {
library.AddClassMetadata(*out_class, toplevel_class,
TokenPosition::kNoSource,
class_offset - correction_offset_, 0);
class_offset - correction_offset_);
}
// We do not register expression evaluation classes with the VM:
@@ -1640,8 +1607,7 @@ void KernelLoader::FinishClassLoading(const Class& klass,
}
if ((FLAG_enable_mirrors || has_pragma_annotation) &&
annotation_count > 0) {
library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
0);
library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset);
}
fields_.Add(&field);
}
@@ -1740,7 +1706,7 @@ void KernelLoader::FinishClassLoading(const Class& klass,
if ((FLAG_enable_mirrors || has_pragma_annotation) &&
annotation_count > 0) {
library.AddFunctionMetadata(function, TokenPosition::kNoSource,
constructor_offset, 0);
constructor_offset);
}
}
@@ -1779,7 +1745,6 @@ void KernelLoader::FinishClassLoading(const Class& klass,
}
void KernelLoader::FinishLoading(const Class& klass) {
ASSERT(!klass.is_declared_in_bytecode());
ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0));
Zone* zone = Thread::Current()->zone();
@@ -2087,7 +2052,7 @@ void KernelLoader::LoadProcedure(const Library& library,
if (annotation_count > 0) {
library.AddFunctionMetadata(function, TokenPosition::kNoSource,
procedure_offset, 0);
procedure_offset);
}
if (has_pragma_annotation) {
@@ -2410,11 +2375,9 @@ FunctionPtr CreateFieldInitializerFunction(Thread* thread,
const PatchClass& initializer_owner =
PatchClass::Handle(zone, PatchClass::New(field_owner, script));
const Library& lib = Library::Handle(zone, field_owner.library());
if (!lib.is_declared_in_bytecode()) {
initializer_owner.set_library_kernel_data(
ExternalTypedData::Handle(zone, lib.kernel_data()));
initializer_owner.set_library_kernel_offset(lib.kernel_offset());
}
initializer_owner.set_library_kernel_data(
ExternalTypedData::Handle(zone, lib.kernel_data()));
initializer_owner.set_library_kernel_offset(lib.kernel_offset());
// Create a static initializer.
const Function& initializer_fun = Function::Handle(
@@ -2441,7 +2404,7 @@ FunctionPtr CreateFieldInitializerFunction(Thread* thread,
initializer_fun.set_token_pos(field.token_pos());
initializer_fun.set_end_token_pos(field.end_token_pos());
initializer_fun.set_accessor_field(field);
initializer_fun.InheritBinaryDeclarationFrom(field);
initializer_fun.InheritKernelOffsetFrom(field);
initializer_fun.set_is_extension_member(field.is_extension_member());
field.SetInitializerFunction(initializer_fun);
return initializer_fun.raw();
-2
View File
@@ -8,7 +8,6 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/bit_vector.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/hash_map.h"
@@ -410,7 +409,6 @@ class KernelLoader : public ValueObject {
ConstantReader constant_reader_;
TypeTranslator type_translator_;
InferredTypeMetadataHelper inferred_type_metadata_helper_;
BytecodeMetadataHelper bytecode_metadata_helper_;
Class& external_name_class_;
Field& external_name_field_;
-20
View File
@@ -207,26 +207,6 @@ DART_EXPORT Dart_Handle Dart_CompileAll() {
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_ReadAllBytecode() {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot read bytecode on an AOT runtime.",
CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(result)) {
return result;
}
CHECK_CALLBACK_STATE(T);
const Error& error = Error::Handle(T->zone(), Library::ReadAllBytecode());
if (!error.IsNull()) {
return Api::NewHandle(T, error.raw());
}
return Api::Success();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: All classes are already finalized in AOT runtime.",
+1 -2
View File
@@ -234,10 +234,9 @@ class NativeArguments {
: public BitField<intptr_t, bool, kReverseArgOrderBit, 1> {};
friend class Api;
friend class NativeEntry;
friend class Interpreter;
friend class Simulator;
// Allow simulator and interpreter to create NativeArguments in reverse order
// Allow simulator to create NativeArguments in reverse order
// on the stack.
NativeArguments(Thread* thread,
int argc_tag,

Some files were not shown because too many files have changed in this diff Show More