4093bdaf5a
Previously catch blocks were hanging off the function entry blocks being effectively an alternative entry-point into the function. Now catch blocks are hanging off the try-entry blocks. Previously all the variables that are used in the catch block and beyond were declared as parameters to catch block. Now only those that have their definitions not dominating catch entry will become parameters (for example, if a variable is assigned in the try-block, it becomes a parameter to catch block). During OSR, if OSR target entry point is inside some try-blocks, then all of corresponding try-entry/catch-blocks are pulled up to the OSR entry forming a chain that ends with a jump to the OSR target entry. TEST=vm/dart/trycatch*, ci Change-Id: Iae20c6548d5d65c63be6d7a53c1b0d2adac7ac31 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/356311 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Slava Egorov <vegorov@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
244 lines
7.3 KiB
C++
244 lines
7.3 KiB
C++
// 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_COMPILER_STATE_H_
|
|
#define RUNTIME_VM_COMPILER_COMPILER_STATE_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/api/deopt_id.h"
|
|
#include "vm/compiler/cha.h"
|
|
#include "vm/heap/safepoint.h"
|
|
#include "vm/thread.h"
|
|
#include "vm/timer.h"
|
|
|
|
namespace dart {
|
|
|
|
class CompilerPass;
|
|
struct CompilerPassState;
|
|
class Function;
|
|
class LocalScope;
|
|
class LocalVariable;
|
|
class SlotCache;
|
|
class Slot;
|
|
|
|
enum class CompilerTracing {
|
|
kOn,
|
|
kOff,
|
|
};
|
|
|
|
struct FunctionPragmas : public ZoneAllocated {
|
|
explicit FunctionPragmas(const Function& function);
|
|
|
|
const Function& function;
|
|
const bool unsafe_no_bounds_checks;
|
|
};
|
|
|
|
struct FunctionPragmasTrait {
|
|
typedef FunctionPragmas* Value;
|
|
typedef const Function* Key;
|
|
typedef FunctionPragmas* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return &kv->function; }
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
static inline uword Hash(Key key) { return key->Hash(); }
|
|
static inline bool IsKeyEqual(Pair kv, Key key) {
|
|
return (kv->function.ptr() == key->ptr());
|
|
}
|
|
};
|
|
using CachedPragmasMap = ZoneDirectChainedHashMap<FunctionPragmasTrait>;
|
|
|
|
// Global compiler state attached to the thread.
|
|
class CompilerState : public ThreadStackResource {
|
|
public:
|
|
CompilerState(Thread* thread,
|
|
bool is_aot,
|
|
bool is_optimizing,
|
|
CompilerTracing tracing = CompilerTracing::kOn)
|
|
: ThreadStackResource(thread),
|
|
cha_(thread),
|
|
is_aot_(is_aot),
|
|
is_optimizing_(is_optimizing),
|
|
tracing_(tracing) {
|
|
previous_ = thread->SetCompilerState(this);
|
|
}
|
|
|
|
~CompilerState() {
|
|
ASSERT(&thread()->compiler_state() == this);
|
|
thread()->SetCompilerState(previous_);
|
|
}
|
|
|
|
CHA& cha() { return cha_; }
|
|
|
|
intptr_t deopt_id() const { return deopt_id_; }
|
|
void set_deopt_id(int value) {
|
|
ASSERT(value >= 0);
|
|
deopt_id_ = value;
|
|
}
|
|
|
|
intptr_t GetNextDeoptId() {
|
|
ASSERT(deopt_id_ != DeoptId::kNone);
|
|
const intptr_t id = deopt_id_;
|
|
deopt_id_ = DeoptId::Next(deopt_id_);
|
|
return id;
|
|
}
|
|
|
|
static CompilerState& Current() {
|
|
return Thread::Current()->compiler_state();
|
|
}
|
|
|
|
SlotCache* slot_cache() const { return slot_cache_; }
|
|
void set_slot_cache(SlotCache* cache) { slot_cache_ = cache; }
|
|
|
|
bool is_aot() const { return is_aot_; }
|
|
|
|
bool is_optimizing() const { return is_optimizing_; }
|
|
bool should_clone_fields() {
|
|
return !is_aot() && (is_optimizing() || FLAG_force_clone_compiler_objects);
|
|
}
|
|
|
|
bool should_trace() const { return tracing_ == CompilerTracing::kOn; }
|
|
|
|
static bool ShouldTrace() { return Current().should_trace(); }
|
|
|
|
static CompilerTracing ShouldTrace(const Function& func);
|
|
|
|
// Returns class Comparable<T> from dart:core.
|
|
const Class& ComparableClass();
|
|
|
|
// Returns _StringBase._interpolate
|
|
const Function& StringBaseInterpolate();
|
|
|
|
// Returns _StringBase._interpolateSingle
|
|
const Function& StringBaseInterpolateSingle();
|
|
|
|
const Function& TypedListGetFloat32();
|
|
const Function& TypedListSetFloat32();
|
|
const Function& TypedListGetFloat64();
|
|
const Function& TypedListSetFloat64();
|
|
const Function& TypedListGetFloat32x4();
|
|
const Function& TypedListSetFloat32x4();
|
|
const Function& TypedListGetInt32x4();
|
|
const Function& TypedListSetInt32x4();
|
|
const Function& TypedListGetFloat64x2();
|
|
const Function& TypedListSetFloat64x2();
|
|
|
|
const Class& ArrayClass();
|
|
const Class& CompoundClass();
|
|
const Class& ErrorClass();
|
|
const Class& StructClass();
|
|
const Class& TypedDataClass();
|
|
const Class& UnionClass();
|
|
|
|
const Field& CompoundOffsetInBytesField();
|
|
const Field& CompoundTypedDataBaseField();
|
|
const Field& ErrorStackTraceField();
|
|
|
|
const Function* function() const { return function_; }
|
|
|
|
void set_function(const Function& function) { function_ = &function; }
|
|
void set_current_pass(const CompilerPass* pass,
|
|
const CompilerPassState* pass_state) {
|
|
pass_ = pass;
|
|
pass_state_ = pass_state;
|
|
}
|
|
|
|
const CompilerPass* pass() const { return pass_; }
|
|
const CompilerPassState* pass_state() const { return pass_state_; }
|
|
|
|
void ReportCrash();
|
|
|
|
const FunctionPragmas& PragmasOf(const Function& function);
|
|
|
|
private:
|
|
const Class& TypedListClass();
|
|
|
|
CHA cha_;
|
|
intptr_t deopt_id_ = 0;
|
|
|
|
// Cache for Slot objects created during compilation (see slot.h).
|
|
SlotCache* slot_cache_ = nullptr;
|
|
|
|
// Caches for dummy LocalVariables and context Slots.
|
|
ZoneGrowableArray<ZoneGrowableArray<const Slot*>*>* dummy_slots_ = nullptr;
|
|
ZoneGrowableArray<LocalVariable*>* dummy_captured_vars_ = nullptr;
|
|
|
|
const bool is_aot_;
|
|
const bool is_optimizing_;
|
|
|
|
const CompilerTracing tracing_;
|
|
|
|
// Lookup cache for various classes (to avoid polluting object store with
|
|
// compiler specific classes).
|
|
const Class* comparable_class_ = nullptr;
|
|
const Function* interpolate_ = nullptr;
|
|
const Function* interpolate_single_ = nullptr;
|
|
const Class* typed_list_class_ = nullptr;
|
|
const Class* array_class_ = nullptr;
|
|
const Class* compound_class_ = nullptr;
|
|
const Class* struct_class_ = nullptr;
|
|
const Class* typed_data_class_ = nullptr;
|
|
const Class* union_class_ = nullptr;
|
|
const Field* compound_offset_in_bytes_field_ = nullptr;
|
|
const Field* compound_typed_data_base_field_ = nullptr;
|
|
const Field* error_stack_trace_field_ = nullptr;
|
|
const Function* typed_list_get_float32_ = nullptr;
|
|
const Function* typed_list_set_float32_ = nullptr;
|
|
const Function* typed_list_get_float64_ = nullptr;
|
|
const Function* typed_list_set_float64_ = nullptr;
|
|
const Function* typed_list_get_float32x4_ = nullptr;
|
|
const Function* typed_list_set_float32x4_ = nullptr;
|
|
const Function* typed_list_get_int32x4_ = nullptr;
|
|
const Function* typed_list_set_int32x4_ = nullptr;
|
|
const Function* typed_list_get_float64x2_ = nullptr;
|
|
const Function* typed_list_set_float64x2_ = nullptr;
|
|
|
|
const Function* function_ = nullptr;
|
|
const CompilerPass* pass_ = nullptr;
|
|
const CompilerPassState* pass_state_ = nullptr;
|
|
CachedPragmasMap* cached_pragmas_ = nullptr;
|
|
|
|
CompilerState* previous_;
|
|
};
|
|
|
|
class DeoptIdScope : public ThreadStackResource {
|
|
public:
|
|
DeoptIdScope(Thread* thread, intptr_t deopt_id)
|
|
: ThreadStackResource(thread),
|
|
prev_deopt_id_(thread->compiler_state().deopt_id()) {
|
|
thread->compiler_state().set_deopt_id(deopt_id);
|
|
}
|
|
|
|
~DeoptIdScope() { thread()->compiler_state().set_deopt_id(prev_deopt_id_); }
|
|
|
|
private:
|
|
const intptr_t prev_deopt_id_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(DeoptIdScope);
|
|
};
|
|
|
|
/// Ensures that there were no deopt id allocations during the lifetime of this
|
|
/// object.
|
|
class AssertNoDeoptIdsAllocatedScope : public ThreadStackResource {
|
|
public:
|
|
explicit AssertNoDeoptIdsAllocatedScope(Thread* thread)
|
|
: ThreadStackResource(thread),
|
|
prev_deopt_id_(thread->compiler_state().deopt_id()) {}
|
|
|
|
~AssertNoDeoptIdsAllocatedScope() {
|
|
ASSERT(thread()->compiler_state().deopt_id() == prev_deopt_id_);
|
|
}
|
|
|
|
private:
|
|
const intptr_t prev_deopt_id_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(AssertNoDeoptIdsAllocatedScope);
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_COMPILER_COMPILER_STATE_H_
|