Files
sdk/runtime/vm/stub_code.h
T
Tess Strickland 0920ac883c [vm] Ensure only generic closures have empty delayed type arguments.
Closures created via Closure::New() set the delayed type arguments to
the null type argument vector for non-generic closure functions and to
the empty type argument vector for generic closure functions.  However,
closures created via the method extractor stub would always have the
empty type argument vector for delayed type arguments.  Make the two
consistent by creating two method extractor stubs, one for generic
extracted methods and one for non-generic ones.

With this change, Closure::IsGeneric simply compares the delayed type
arguments against the empty type argument vector. This change also makes
method extraction for non-generic functions slightly faster, since the
delayed type arguments field is not changed post-allocation.

The old version of Closure::IsGeneric was the only use of
Closure::NumTypeParameters, so remove the latter method.

Related cleanups:

* Use similar checks for Class::IsGeneric and FunctionType::IsGeneric,
  since they only have non-null type_parameters fields when generic.
  For Class::IsGeneric, this avoids having to fetch the current thread
  if the class declaration has been loaded.

* Refactor methods that read packed fields in FunctionType into two
  methods, a static method that takes a FunctionTypePtr and an instance
  method that calls the static method. Replace the methods in Function
  that also directly read FunctionType packed fields with delegations to
  the static methods.

* Rework Closure_equals to avoid unneeded handle allocation in certain
  cases for non-equal closures.

* Replace cases that allocates a handle for the closure function only
  for retrieving the signature with calls to Closure::signature().

TEST=language_2/closure/tearoff_dynamic_test
     language_2/regress/regress45890_test

Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64c-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-nnbd-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try,vm-kernel-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try
Change-Id: I29c8859c3350ed7b3f1a8f71d82a4393496b7c2b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206820
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
2021-07-15 22:51:57 +00:00

144 lines
4.9 KiB
C++

// Copyright (c) 2011, 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_STUB_CODE_H_
#define RUNTIME_VM_STUB_CODE_H_
#include "vm/allocation.h"
#include "vm/compiler/runtime_api.h"
#include "vm/object.h"
#include "vm/stub_code_list.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/stub_code_compiler.h"
#endif // !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
// Forward declarations.
class Code;
class Isolate;
class ObjectPointerVisitor;
class SnapshotReader;
class SnapshotWriter;
DECLARE_FLAG(bool, disassemble_stubs);
// Is it permitted for the stubs above to refer to Object::null(), which is
// allocated in the VM isolate and shared across all isolates.
// However, in cases where a simple GC-safe placeholder is needed on the stack,
// using Smi 0 instead of Object::null() is slightly more efficient, since a Smi
// does not require relocation.
// class StubCode is used to maintain the lifecycle of stubs.
class StubCode : public AllStatic {
public:
// Generate all stubs which are shared across all isolates, this is done
// only once and the stub code resides in the vm_isolate heap.
static void Init();
static void Cleanup();
// Returns true if stub code has been initialized.
static bool HasBeenInitialized() {
return initialized_.load(std::memory_order_acquire);
}
static void InitializationDone() {
initialized_.store(true, std::memory_order_release);
}
// Check if specified pc is in the dart invocation stub used for
// transitioning into dart code.
static bool InInvocationStub(uword pc);
// Check if the specified pc is in the jump to frame stub.
static bool InJumpToFrameStub(uword pc);
// Returns NULL if no stub found.
static const char* NameOfStub(uword entry_point);
// Define the shared stub code accessors.
#define STUB_CODE_ACCESSOR(name) \
static const Code& name() { return *entries_[k##name##Index].code; } \
static intptr_t name##Size() { return name().Size(); }
VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
#undef STUB_CODE_ACCESSOR
#if !defined(DART_PRECOMPILED_RUNTIME)
static CodePtr GetAllocationStubForClass(const Class& cls);
static CodePtr GetAllocationStubForTypedData(classid_t class_id);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(TARGET_ARCH_IA32)
static CodePtr GetBuildGenericMethodExtractorStub(
compiler::ObjectPoolBuilder* pool) {
return GetBuildMethodExtractorStub(pool, /*generic=*/true);
}
static CodePtr GetBuildNonGenericMethodExtractorStub(
compiler::ObjectPoolBuilder* pool) {
return GetBuildMethodExtractorStub(pool, /*generic=*/false);
}
#endif
#if !defined(DART_PRECOMPILED_RUNTIME)
// Generate the stub and finalize the generated code into the stub
// code executable area.
static CodePtr Generate(const char* name,
compiler::ObjectPoolBuilder* object_pool_builder,
void (*GenerateStub)(compiler::Assembler* assembler));
#endif // !defined(DART_PRECOMPILED_RUNTIME)
static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested);
static const char* NameAt(intptr_t index) { return entries_[index].name; }
static const Code& EntryAt(intptr_t index) { return *(entries_[index].code); }
static void EntryAtPut(intptr_t index, Code* entry) {
ASSERT(entry->IsReadOnlyHandle());
ASSERT(entries_[index].code == nullptr);
entries_[index].code = entry;
}
static intptr_t NumEntries() { return kNumStubEntries; }
#if !defined(DART_PRECOMPILED_RUNTIME)
#define GENERATE_STUB(name) \
static CodePtr BuildIsolateSpecific##name##Stub( \
compiler::ObjectPoolBuilder* opw) { \
return StubCode::Generate( \
"_iso_stub_" #name, opw, \
compiler::StubCodeCompiler::Generate##name##Stub); \
}
VM_STUB_CODE_LIST(GENERATE_STUB);
#undef GENERATE_STUB
#endif // !defined(DART_PRECOMPILED_RUNTIME)
private:
friend class MegamorphicCacheTable;
static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
bool generic);
enum {
#define STUB_CODE_ENTRY(name) k##name##Index,
VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
#undef STUB_CODE_ENTRY
kNumStubEntries
};
struct StubCodeEntry {
Code* code;
const char* name;
#if !defined(DART_PRECOMPILED_RUNTIME)
void (*generator)(compiler::Assembler* assembler);
#endif
};
static StubCodeEntry entries_[kNumStubEntries];
static AcqRelAtomic<bool> initialized_;
};
} // namespace dart
#endif // RUNTIME_VM_STUB_CODE_H_