[builtins] remove redundant builtins lists.
R=bmeurer@chromium.org BUG=v8:5197 Review-Url: https://codereview.chromium.org/2155633002 Cr-Commit-Position: refs/heads/master@{#37820}
This commit is contained in:
parent
f4234422b9
commit
c06ad0867e
@ -896,10 +896,8 @@ void ExternalReference::SetUp() {
|
||||
static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
|
||||
}
|
||||
|
||||
|
||||
ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate)
|
||||
: address_(Redirect(isolate, Builtins::c_function_address(id))) {}
|
||||
|
||||
ExternalReference::ExternalReference(Address address, Isolate* isolate)
|
||||
: address_(Redirect(isolate, address)) {}
|
||||
|
||||
ExternalReference::ExternalReference(
|
||||
ApiFunction* fun,
|
||||
|
@ -859,7 +859,7 @@ class ExternalReference BASE_EMBEDDED {
|
||||
|
||||
ExternalReference() : address_(NULL) {}
|
||||
|
||||
ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
|
||||
ExternalReference(Address address, Isolate* isolate);
|
||||
|
||||
ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : number of arguments excluding receiver
|
||||
@ -44,7 +44,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(r0, r1, r3);
|
||||
__ SmiUntag(r0);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
|
||||
__ LoadNativeContextSlot(Context::INTERNAL_ARRAY_FUNCTION_INDEX, result);
|
||||
}
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x0 : number of arguments excluding receiver
|
||||
@ -58,7 +58,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(x0, x1, x3);
|
||||
__ SmiUntag(x0);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ class BuiltinArguments : public Arguments {
|
||||
return Builtin_Impl_##name(args, isolate); \
|
||||
} \
|
||||
\
|
||||
MUST_USE_RESULT static Object* Builtin_##name( \
|
||||
MUST_USE_RESULT Object* Builtin_##name( \
|
||||
int args_length, Object** args_object, Isolate* isolate) { \
|
||||
DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \
|
||||
if (FLAG_runtime_call_stats) { \
|
||||
@ -6408,209 +6408,95 @@ void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
|
||||
|
||||
Builtins::Builtins() : initialized_(false) {
|
||||
memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
|
||||
memset(names_, 0, sizeof(names_[0]) * builtin_count);
|
||||
}
|
||||
|
||||
Builtins::~Builtins() {}
|
||||
|
||||
#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
|
||||
Address const Builtins::c_functions_[cfunction_count] = {
|
||||
BUILTIN_LIST_C(DEF_ENUM_C)};
|
||||
#undef DEF_ENUM_C
|
||||
|
||||
struct BuiltinDesc {
|
||||
Handle<Code> (*builder)(Isolate*, struct BuiltinDesc const*);
|
||||
byte* generator;
|
||||
byte* c_code;
|
||||
const char* s_name; // name is only used for generating log information.
|
||||
int name;
|
||||
Code::Flags flags;
|
||||
Builtins::ExitFrameType exit_frame_type;
|
||||
int argc;
|
||||
};
|
||||
|
||||
#define BUILTIN_FUNCTION_TABLE_INIT \
|
||||
{ \
|
||||
V8_ONCE_INIT, {} \
|
||||
}
|
||||
|
||||
class BuiltinFunctionTable {
|
||||
public:
|
||||
BuiltinDesc* functions() {
|
||||
base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
|
||||
return functions_;
|
||||
}
|
||||
|
||||
base::OnceType once_;
|
||||
BuiltinDesc functions_[Builtins::builtin_count + 1];
|
||||
|
||||
friend class Builtins;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT;
|
||||
|
||||
Handle<Code> MacroAssemblerBuilder(Isolate* isolate,
|
||||
BuiltinDesc const* builtin_desc) {
|
||||
// For now we generate builtin adaptor code into a stack-allocated
|
||||
// buffer, before copying it into individual code objects. Be careful
|
||||
// with alignment, some platforms don't like unaligned code.
|
||||
#ifdef DEBUG
|
||||
// We can generate a lot of debug code on Arm64.
|
||||
const size_t buffer_size = 32 * KB;
|
||||
#elif V8_TARGET_ARCH_PPC64
|
||||
// 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
|
||||
const size_t buffer_size = 10 * KB;
|
||||
#else
|
||||
const size_t buffer_size = 8 * KB;
|
||||
void PostBuildProfileAndTracing(Isolate* isolate, Code* code,
|
||||
const char* name) {
|
||||
PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
|
||||
AbstractCode::cast(code), name));
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
if (FLAG_print_builtin_code) {
|
||||
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
|
||||
OFStream os(trace_scope.file());
|
||||
os << "Builtin: " << name << "\n";
|
||||
code->Disassemble(name, os);
|
||||
os << "\n";
|
||||
}
|
||||
#endif
|
||||
union {
|
||||
int force_alignment;
|
||||
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
|
||||
} u;
|
||||
}
|
||||
|
||||
MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
|
||||
CodeObjectRequired::kYes);
|
||||
// Generate the code/adaptor.
|
||||
typedef void (*Generator)(MacroAssembler*, int, Builtins::ExitFrameType);
|
||||
Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
|
||||
// We pass all arguments to the generator, but it may not use all of
|
||||
// them. This works because the first arguments are on top of the
|
||||
// stack.
|
||||
typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
|
||||
typedef void (*CodeAssemblerGenerator)(CodeStubAssembler*);
|
||||
|
||||
Code* BuildWithMacroAssembler(Isolate* isolate,
|
||||
MacroAssemblerGenerator generator,
|
||||
Code::Flags flags, const char* s_name) {
|
||||
HandleScope scope(isolate);
|
||||
const size_t buffer_size = 32 * KB;
|
||||
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
|
||||
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
|
||||
DCHECK(!masm.has_frame());
|
||||
g(&masm, builtin_desc->name, builtin_desc->exit_frame_type);
|
||||
// Move the code into the object heap.
|
||||
generator(&masm);
|
||||
CodeDesc desc;
|
||||
masm.GetCode(&desc);
|
||||
Code::Flags flags = builtin_desc->flags;
|
||||
return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
|
||||
Handle<Code> code =
|
||||
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
|
||||
PostBuildProfileAndTracing(isolate, *code, s_name);
|
||||
return *code;
|
||||
}
|
||||
|
||||
Code* BuildAdaptor(Isolate* isolate, Address builtin_address,
|
||||
Builtins::ExitFrameType exit_frame_type, Code::Flags flags,
|
||||
const char* name) {
|
||||
HandleScope scope(isolate);
|
||||
const size_t buffer_size = 32 * KB;
|
||||
byte buffer[buffer_size]; // NOLINT(runtime/arrays)
|
||||
MacroAssembler masm(isolate, buffer, buffer_size, CodeObjectRequired::kYes);
|
||||
DCHECK(!masm.has_frame());
|
||||
Builtins::Generate_Adaptor(&masm, builtin_address, exit_frame_type);
|
||||
CodeDesc desc;
|
||||
masm.GetCode(&desc);
|
||||
Handle<Code> code =
|
||||
isolate->factory()->NewCode(desc, flags, masm.CodeObject());
|
||||
PostBuildProfileAndTracing(isolate, *code, name);
|
||||
return *code;
|
||||
}
|
||||
|
||||
// Builder for builtins implemented in TurboFan with JS linkage.
|
||||
Handle<Code> CodeStubAssemblerBuilderJS(Isolate* isolate,
|
||||
BuiltinDesc const* builtin_desc) {
|
||||
Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
|
||||
CodeAssemblerGenerator generator, int argc,
|
||||
Code::Flags flags, const char* name) {
|
||||
HandleScope scope(isolate);
|
||||
Zone zone(isolate->allocator());
|
||||
CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
|
||||
builtin_desc->flags, builtin_desc->s_name);
|
||||
// Generate the code/adaptor.
|
||||
typedef void (*Generator)(CodeStubAssembler*);
|
||||
Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
|
||||
g(&assembler);
|
||||
return assembler.GenerateCode();
|
||||
CodeStubAssembler assembler(isolate, &zone, argc, flags, name);
|
||||
generator(&assembler);
|
||||
Handle<Code> code = assembler.GenerateCode();
|
||||
PostBuildProfileAndTracing(isolate, *code, name);
|
||||
return *code;
|
||||
}
|
||||
|
||||
// Builder for builtins implemented in TurboFan with CallStub linkage.
|
||||
Handle<Code> CodeStubAssemblerBuilderCS(Isolate* isolate,
|
||||
BuiltinDesc const* builtin_desc) {
|
||||
Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
|
||||
CodeAssemblerGenerator generator,
|
||||
CallDescriptors::Key interface_descriptor,
|
||||
Code::Flags flags, const char* name) {
|
||||
HandleScope scope(isolate);
|
||||
Zone zone(isolate->allocator());
|
||||
// The interface descriptor with given key must be initialized at this point
|
||||
// and this construction just queries the details from the descriptors table.
|
||||
CallInterfaceDescriptor descriptor(
|
||||
isolate, static_cast<CallDescriptors::Key>(builtin_desc->argc));
|
||||
CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
|
||||
// Ensure descriptor is already initialized.
|
||||
DCHECK_NOT_NULL(descriptor.GetFunctionType());
|
||||
CodeStubAssembler assembler(isolate, &zone, descriptor, builtin_desc->flags,
|
||||
builtin_desc->s_name);
|
||||
// Generate the code/adaptor.
|
||||
typedef void (*Generator)(CodeStubAssembler*);
|
||||
Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
|
||||
g(&assembler);
|
||||
return assembler.GenerateCode();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Define array of pointers to generators and C builtin functions.
|
||||
// We do this in a sort of roundabout way so that we can do the initialization
|
||||
// within the lexical scope of Builtins:: and within a context where
|
||||
// Code::Flags names a non-abstract type.
|
||||
void Builtins::InitBuiltinFunctionTable() {
|
||||
BuiltinDesc* functions = builtin_function_table.functions_;
|
||||
functions[builtin_count].builder = nullptr;
|
||||
functions[builtin_count].generator = nullptr;
|
||||
functions[builtin_count].c_code = nullptr;
|
||||
functions[builtin_count].s_name = nullptr;
|
||||
functions[builtin_count].name = builtin_count;
|
||||
functions[builtin_count].flags = static_cast<Code::Flags>(0);
|
||||
functions[builtin_count].exit_frame_type = EXIT;
|
||||
functions[builtin_count].argc = 0;
|
||||
|
||||
#define DEF_CPP(Name) \
|
||||
functions->builder = &MacroAssemblerBuilder; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
||||
functions->c_code = FUNCTION_ADDR(Builtin_##Name); \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = c_##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
||||
functions->exit_frame_type = BUILTIN_EXIT; \
|
||||
functions->argc = 0; \
|
||||
++functions;
|
||||
|
||||
#define DEF_API(Name) \
|
||||
functions->builder = &MacroAssemblerBuilder; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
||||
functions->c_code = FUNCTION_ADDR(Builtin_##Name); \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = c_##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
||||
functions->exit_frame_type = EXIT; \
|
||||
functions->argc = 0; \
|
||||
++functions;
|
||||
|
||||
#define DEF_TFJ(Name, Argc) \
|
||||
functions->builder = &CodeStubAssemblerBuilderJS; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_##Name); \
|
||||
functions->c_code = NULL; \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = k##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
||||
functions->exit_frame_type = EXIT; \
|
||||
functions->argc = Argc; \
|
||||
++functions;
|
||||
|
||||
#define DEF_TFS(Name, Kind, Extra, InterfaceDescriptor) \
|
||||
functions->builder = &CodeStubAssemblerBuilderCS; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_##Name); \
|
||||
functions->c_code = NULL; \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = k##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::Kind, Extra); \
|
||||
functions->exit_frame_type = EXIT; \
|
||||
functions->argc = CallDescriptors::InterfaceDescriptor; \
|
||||
++functions;
|
||||
|
||||
#define DEF_ASM(Name) \
|
||||
functions->builder = &MacroAssemblerBuilder; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_##Name); \
|
||||
functions->c_code = NULL; \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = k##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
||||
functions->exit_frame_type = EXIT; \
|
||||
functions->argc = 0; \
|
||||
++functions;
|
||||
|
||||
#define DEF_ASH(Name, Kind, Extra) \
|
||||
functions->builder = &MacroAssemblerBuilder; \
|
||||
functions->generator = FUNCTION_ADDR(Generate_##Name); \
|
||||
functions->c_code = NULL; \
|
||||
functions->s_name = #Name; \
|
||||
functions->name = k##Name; \
|
||||
functions->flags = Code::ComputeFlags(Code::Kind, Extra); \
|
||||
functions->exit_frame_type = EXIT; \
|
||||
functions->argc = 0; \
|
||||
++functions;
|
||||
|
||||
BUILTIN_LIST(DEF_CPP, DEF_API, DEF_TFJ, DEF_TFS, DEF_ASM, DEF_ASH, DEF_ASM)
|
||||
|
||||
#undef DEF_CPP
|
||||
#undef DEF_API
|
||||
#undef DEF_TFJ
|
||||
#undef DEF_TFS
|
||||
#undef DEF_ASM
|
||||
#undef DEF_ASH
|
||||
CodeStubAssembler assembler(isolate, &zone, descriptor, flags, name);
|
||||
generator(&assembler);
|
||||
Handle<Code> code = assembler.GenerateCode();
|
||||
PostBuildProfileAndTracing(isolate, *code, name);
|
||||
return *code;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
|
||||
DCHECK(!initialized_);
|
||||
@ -6618,38 +6504,50 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
|
||||
// Create a scope for the handles in the builtins.
|
||||
HandleScope scope(isolate);
|
||||
|
||||
#define INITIALIZE_CALL_DESCRIPTOR(name, kind, extra, interface_descriptor) \
|
||||
{ interface_descriptor##Descriptor descriptor(isolate); }
|
||||
BUILTIN_LIST_TFS(INITIALIZE_CALL_DESCRIPTOR)
|
||||
#undef INITIALIZE_CALL_DESCRIPTOR
|
||||
if (create_heap_objects) {
|
||||
int index = 0;
|
||||
const Code::Flags kBuiltinFlags = Code::ComputeFlags(Code::BUILTIN);
|
||||
Code* code;
|
||||
#define BUILD_CPP(Name) \
|
||||
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), BUILTIN_EXIT, \
|
||||
kBuiltinFlags, #Name); \
|
||||
builtins_[index++] = code;
|
||||
#define BUILD_API(Name) \
|
||||
code = BuildAdaptor(isolate, FUNCTION_ADDR(Builtin_##Name), EXIT, \
|
||||
kBuiltinFlags, #Name); \
|
||||
builtins_[index++] = code;
|
||||
#define BUILD_TFJ(Name, Argc) \
|
||||
code = BuildWithCodeStubAssemblerJS(isolate, &Generate_##Name, Argc, \
|
||||
kBuiltinFlags, #Name); \
|
||||
builtins_[index++] = code;
|
||||
#define BUILD_TFS(Name, Kind, Extra, InterfaceDescriptor) \
|
||||
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
|
||||
code = BuildWithCodeStubAssemblerCS( \
|
||||
isolate, &Generate_##Name, CallDescriptors::InterfaceDescriptor, \
|
||||
Code::ComputeFlags(Code::Kind, Extra), #Name); \
|
||||
builtins_[index++] = code;
|
||||
#define BUILD_ASM(Name) \
|
||||
code = \
|
||||
BuildWithMacroAssembler(isolate, Generate_##Name, kBuiltinFlags, #Name); \
|
||||
builtins_[index++] = code;
|
||||
#define BUILD_ASH(Name, Kind, Extra) \
|
||||
code = BuildWithMacroAssembler( \
|
||||
isolate, Generate_##Name, Code::ComputeFlags(Code::Kind, Extra), #Name); \
|
||||
builtins_[index++] = code;
|
||||
|
||||
const BuiltinDesc* functions = builtin_function_table.functions();
|
||||
BUILTIN_LIST(BUILD_CPP, BUILD_API, BUILD_TFJ, BUILD_TFS, BUILD_ASM,
|
||||
BUILD_ASH, BUILD_ASM);
|
||||
|
||||
// Traverse the list of builtins and generate an adaptor in a
|
||||
// separate code object for each one.
|
||||
for (int i = 0; i < builtin_count; i++) {
|
||||
if (create_heap_objects) {
|
||||
Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
|
||||
// Log the event and add the code to the builtins array.
|
||||
PROFILE(isolate,
|
||||
CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
|
||||
AbstractCode::cast(*code), functions[i].s_name));
|
||||
builtins_[i] = *code;
|
||||
code->set_builtin_index(i);
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
if (FLAG_print_builtin_code) {
|
||||
CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
|
||||
OFStream os(trace_scope.file());
|
||||
os << "Builtin: " << functions[i].s_name << "\n";
|
||||
code->Disassemble(functions[i].s_name, os);
|
||||
os << "\n";
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// Deserializing. The values will be filled in during IterateBuiltins.
|
||||
builtins_[i] = NULL;
|
||||
#undef BUILD_CPP
|
||||
#undef BUILD_API
|
||||
#undef BUILD_TFJ
|
||||
#undef BUILD_TFS
|
||||
#undef BUILD_ASM
|
||||
#undef BUILD_ASH
|
||||
CHECK_EQ(builtin_count, index);
|
||||
for (int i = 0; i < builtin_count; i++) {
|
||||
Code::cast(builtins_[i])->set_builtin_index(i);
|
||||
}
|
||||
names_[i] = functions[i].s_name;
|
||||
}
|
||||
|
||||
// Mark as initialized.
|
||||
@ -6667,14 +6565,26 @@ const char* Builtins::Lookup(byte* pc) {
|
||||
if (initialized_) {
|
||||
for (int i = 0; i < builtin_count; i++) {
|
||||
Code* entry = Code::cast(builtins_[i]);
|
||||
if (entry->contains(pc)) {
|
||||
return names_[i];
|
||||
}
|
||||
if (entry->contains(pc)) return name(i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Builtins::name(int index) {
|
||||
switch (index) {
|
||||
#define CASE(Name, ...) \
|
||||
case k##Name: \
|
||||
return #Name;
|
||||
BUILTIN_LIST_ALL(CASE)
|
||||
#undef CASE
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
|
||||
masm->TailCallRuntime(Runtime::kInterrupt);
|
||||
}
|
||||
|
@ -392,17 +392,12 @@ namespace internal {
|
||||
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
|
||||
V, V, V)
|
||||
|
||||
#define BUILTIN_LIST_TFS(V) \
|
||||
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, V, \
|
||||
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
|
||||
|
||||
#define BUILTIN_LIST_DBG(V) \
|
||||
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
|
||||
IGNORE_BUILTIN, IGNORE_BUILTIN, V)
|
||||
|
||||
// Forward declarations.
|
||||
class CodeStubAssembler;
|
||||
class BuiltinFunctionTable;
|
||||
class ObjectVisitor;
|
||||
|
||||
class Builtins {
|
||||
@ -421,20 +416,13 @@ class Builtins {
|
||||
const char* Lookup(byte* pc);
|
||||
|
||||
enum Name {
|
||||
#define DEF_ENUM(name, ...) k##name,
|
||||
#define DEF_ENUM(Name, ...) k##Name,
|
||||
BUILTIN_LIST_ALL(DEF_ENUM)
|
||||
#undef DEF_ENUM
|
||||
builtin_count
|
||||
};
|
||||
|
||||
enum CFunctionId {
|
||||
#define DEF_ENUM(name) c_##name,
|
||||
BUILTIN_LIST_C(DEF_ENUM)
|
||||
#undef DEF_ENUM
|
||||
cfunction_count
|
||||
};
|
||||
|
||||
#define DECLARE_BUILTIN_ACCESSOR(name, ...) Handle<Code> name();
|
||||
#define DECLARE_BUILTIN_ACCESSOR(Name, ...) Handle<Code> Name();
|
||||
BUILTIN_LIST_ALL(DECLARE_BUILTIN_ACCESSOR)
|
||||
#undef DECLARE_BUILTIN_ACCESSOR
|
||||
|
||||
@ -462,13 +450,7 @@ class Builtins {
|
||||
return reinterpret_cast<Address>(&builtins_[name]);
|
||||
}
|
||||
|
||||
static Address c_function_address(CFunctionId id) { return c_functions_[id]; }
|
||||
|
||||
const char* name(int index) {
|
||||
DCHECK(index >= 0);
|
||||
DCHECK(index < builtin_count);
|
||||
return names_[index];
|
||||
}
|
||||
const char* name(int index);
|
||||
|
||||
bool is_initialized() const { return initialized_; }
|
||||
|
||||
@ -478,20 +460,12 @@ class Builtins {
|
||||
|
||||
enum ExitFrameType { EXIT, BUILTIN_EXIT };
|
||||
|
||||
static void Generate_Adaptor(MacroAssembler* masm, Address builtin_address,
|
||||
ExitFrameType exit_frame_type);
|
||||
|
||||
private:
|
||||
Builtins();
|
||||
|
||||
// The external C++ functions called from the code.
|
||||
static Address const c_functions_[cfunction_count];
|
||||
|
||||
// Note: These are always Code objects, but to conform with
|
||||
// IterateBuiltins() above which assumes Object**'s for the callback
|
||||
// function f, we use an Object* array here.
|
||||
Object* builtins_[builtin_count];
|
||||
const char* names_[builtin_count];
|
||||
|
||||
static void Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
ExitFrameType exit_frame_type);
|
||||
static void Generate_AllocateInNewSpace(MacroAssembler* masm);
|
||||
static void Generate_AllocateInOldSpace(MacroAssembler* masm);
|
||||
static void Generate_ConstructedNonConstructable(MacroAssembler* masm);
|
||||
@ -823,11 +797,12 @@ class Builtins {
|
||||
static void Generate_AtomicsLoad(CodeStubAssembler* assembler);
|
||||
static void Generate_AtomicsStore(CodeStubAssembler* assembler);
|
||||
|
||||
static void InitBuiltinFunctionTable();
|
||||
|
||||
// Note: These are always Code objects, but to conform with
|
||||
// IterateBuiltins() above which assumes Object**'s for the callback
|
||||
// function f, we use an Object* array here.
|
||||
Object* builtins_[builtin_count];
|
||||
bool initialized_;
|
||||
|
||||
friend class BuiltinFunctionTable;
|
||||
friend class Isolate;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Builtins);
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : number of arguments excluding receiver
|
||||
@ -49,7 +49,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(edx);
|
||||
__ PushReturnAddressFrom(ecx);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : number of arguments excluding receiver
|
||||
@ -44,8 +44,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(a0, a1, a3);
|
||||
__ SmiUntag(a0);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()), PROTECT,
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
PROTECT, exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
// Load the built-in InternalArray function from the current context.
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : number of arguments excluding receiver
|
||||
@ -44,8 +44,8 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(a0, a1, a3);
|
||||
__ SmiUntag(a0);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()), PROTECT,
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
PROTECT, exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
// Load the built-in InternalArray function from the current context.
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r3 : number of arguments excluding receiver
|
||||
@ -44,7 +44,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(r3, r4, r6);
|
||||
__ SmiUntag(r3);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : number of arguments excluding receiver
|
||||
@ -44,7 +44,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(r2, r3, r5);
|
||||
__ SmiUntag(r2);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : number of arguments excluding receiver
|
||||
@ -49,7 +49,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(rdx);
|
||||
__ PushReturnAddressFrom(kScratchRegister);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace internal {
|
||||
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
void Builtins::Generate_Adaptor(MacroAssembler* masm, Address address,
|
||||
ExitFrameType exit_frame_type) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : number of arguments excluding receiver
|
||||
@ -49,7 +49,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id,
|
||||
__ Push(edx);
|
||||
__ PushReturnAddressFrom(ecx);
|
||||
|
||||
__ JumpToExternalReference(ExternalReference(id, masm->isolate()),
|
||||
__ JumpToExternalReference(ExternalReference(address, masm->isolate()),
|
||||
exit_frame_type == BUILTIN_EXIT);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "src/accessors.h"
|
||||
#include "src/assembler.h"
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/counters.h"
|
||||
#include "src/deoptimizer.h"
|
||||
#include "src/ic/stub-cache.h"
|
||||
@ -13,6 +14,12 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Forward declarations for C++ builtins.
|
||||
#define FORWARD_DECLARE(Name) \
|
||||
Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
|
||||
BUILTIN_LIST_C(FORWARD_DECLARE)
|
||||
#undef FORWARD_DECLARE
|
||||
|
||||
ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
|
||||
ExternalReferenceTable* external_reference_table =
|
||||
isolate->external_reference_table();
|
||||
@ -24,6 +31,18 @@ ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
|
||||
}
|
||||
|
||||
ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
AddReferences(isolate);
|
||||
AddBuiltins(isolate);
|
||||
AddRuntimeFunctions(isolate);
|
||||
AddStatCounters(isolate);
|
||||
AddIsolateAddresses(isolate);
|
||||
AddAccessors(isolate);
|
||||
AddStubCache(isolate);
|
||||
AddDeoptEntries(isolate);
|
||||
AddApiReferences(isolate);
|
||||
}
|
||||
|
||||
void ExternalReferenceTable::AddReferences(Isolate* isolate) {
|
||||
// Miscellaneous
|
||||
Add(ExternalReference::roots_array_start(isolate).address(),
|
||||
"Heap::roots_array_start()");
|
||||
@ -234,54 +253,68 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
"OffsetsVector::static_offsets_vector");
|
||||
#endif // V8_INTERPRETED_REGEXP
|
||||
|
||||
// The following populates all of the different type of external references
|
||||
// into the ExternalReferenceTable.
|
||||
//
|
||||
// NOTE: This function was originally 100k of code. It has since been
|
||||
// rewritten to be mostly table driven, as the callback macro style tends to
|
||||
// very easily cause code bloat. Please be careful in the future when adding
|
||||
// new references.
|
||||
// Runtime entries
|
||||
Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
|
||||
"HandleScope::DeleteExtensions");
|
||||
Add(ExternalReference::incremental_marking_record_write_function(isolate)
|
||||
.address(),
|
||||
"IncrementalMarking::RecordWrite");
|
||||
Add(ExternalReference::incremental_marking_record_write_code_entry_function(
|
||||
isolate)
|
||||
.address(),
|
||||
"IncrementalMarking::RecordWriteOfCodeEntryFromCode");
|
||||
Add(ExternalReference::store_buffer_overflow_function(isolate).address(),
|
||||
"StoreBuffer::StoreBufferOverflow");
|
||||
}
|
||||
|
||||
struct RefTableEntry {
|
||||
uint16_t id;
|
||||
void ExternalReferenceTable::AddBuiltins(Isolate* isolate) {
|
||||
struct CBuiltinEntry {
|
||||
Address address;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static const RefTableEntry c_builtins[] = {
|
||||
#define DEF_ENTRY(name) {Builtins::c_##name, "Builtins::" #name},
|
||||
static const CBuiltinEntry c_builtins[] = {
|
||||
#define DEF_ENTRY(Name, ...) {FUNCTION_ADDR(&Builtin_##Name), "Builtin_" #Name},
|
||||
BUILTIN_LIST_C(DEF_ENTRY)
|
||||
#undef DEF_ENTRY
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(c_builtins); ++i) {
|
||||
ExternalReference ref(static_cast<Builtins::CFunctionId>(c_builtins[i].id),
|
||||
isolate);
|
||||
Add(ref.address(), c_builtins[i].name);
|
||||
Add(ExternalReference(c_builtins[i].address, isolate).address(),
|
||||
c_builtins[i].name);
|
||||
}
|
||||
|
||||
static const RefTableEntry builtins[] = {
|
||||
#define DEF_ENTRY(name, ...) {Builtins::k##name, "Builtins::" #name},
|
||||
struct BuiltinEntry {
|
||||
Builtins::Name id;
|
||||
const char* name;
|
||||
};
|
||||
static const BuiltinEntry builtins[] = {
|
||||
#define DEF_ENTRY(Name, ...) {Builtins::k##Name, "Builtin_" #Name},
|
||||
BUILTIN_LIST_C(DEF_ENTRY) BUILTIN_LIST_A(DEF_ENTRY)
|
||||
#undef DEF_ENTRY
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(builtins); ++i) {
|
||||
ExternalReference ref(static_cast<Builtins::Name>(builtins[i].id), isolate);
|
||||
Add(ref.address(), builtins[i].name);
|
||||
Add(isolate->builtins()->builtin_address(builtins[i].id), builtins[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static const RefTableEntry runtime_functions[] = {
|
||||
void ExternalReferenceTable::AddRuntimeFunctions(Isolate* isolate) {
|
||||
struct RuntimeEntry {
|
||||
Runtime::FunctionId id;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static const RuntimeEntry runtime_functions[] = {
|
||||
#define RUNTIME_ENTRY(name, i1, i2) {Runtime::k##name, "Runtime::" #name},
|
||||
FOR_EACH_INTRINSIC(RUNTIME_ENTRY)
|
||||
#undef RUNTIME_ENTRY
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(runtime_functions); ++i) {
|
||||
ExternalReference ref(
|
||||
static_cast<Runtime::FunctionId>(runtime_functions[i].id), isolate);
|
||||
ExternalReference ref(runtime_functions[i].id, isolate);
|
||||
Add(ref.address(), runtime_functions[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalReferenceTable::AddStatCounters(Isolate* isolate) {
|
||||
// Stat counters
|
||||
struct StatsRefTableEntry {
|
||||
StatsCounter* (Counters::*counter)();
|
||||
@ -305,7 +338,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
}
|
||||
Add(address, stats_ref_table[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalReferenceTable::AddIsolateAddresses(Isolate* isolate) {
|
||||
// Top addresses
|
||||
static const char* address_names[] = {
|
||||
#define BUILD_NAME_LITERAL(Name, name) "Isolate::" #name "_address",
|
||||
@ -317,7 +352,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
Add(isolate->get_address_from_id(static_cast<Isolate::AddressId>(i)),
|
||||
address_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalReferenceTable::AddAccessors(Isolate* isolate) {
|
||||
// Accessors
|
||||
struct AccessorRefTable {
|
||||
Address address;
|
||||
@ -346,7 +383,9 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
for (unsigned i = 0; i < arraysize(setters); ++i) {
|
||||
Add(setters[i].address, setters[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalReferenceTable::AddStubCache(Isolate* isolate) {
|
||||
StubCache* load_stub_cache = isolate->load_stub_cache();
|
||||
|
||||
// Stub cache tables
|
||||
@ -378,21 +417,11 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
"Store StubCache::secondary_->value");
|
||||
Add(store_stub_cache->map_reference(StubCache::kSecondary).address(),
|
||||
"Store StubCache::secondary_->map");
|
||||
}
|
||||
|
||||
// Runtime entries
|
||||
Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
|
||||
"HandleScope::DeleteExtensions");
|
||||
Add(ExternalReference::incremental_marking_record_write_function(isolate)
|
||||
.address(),
|
||||
"IncrementalMarking::RecordWrite");
|
||||
Add(ExternalReference::incremental_marking_record_write_code_entry_function(
|
||||
isolate)
|
||||
.address(),
|
||||
"IncrementalMarking::RecordWriteOfCodeEntryFromCode");
|
||||
Add(ExternalReference::store_buffer_overflow_function(isolate).address(),
|
||||
"StoreBuffer::StoreBufferOverflow");
|
||||
|
||||
// Add a small set of deopt entry addresses to encoder without generating the
|
||||
void ExternalReferenceTable::AddDeoptEntries(Isolate* isolate) {
|
||||
// Add a small set of deopt entry addresses to encoder without generating
|
||||
// the
|
||||
// deopt table code, which isn't possible at deserialization time.
|
||||
HandleScope scope(isolate);
|
||||
for (int entry = 0; entry < kDeoptTableSerializeEntryCount; ++entry) {
|
||||
@ -401,8 +430,11 @@ ExternalReferenceTable::ExternalReferenceTable(Isolate* isolate) {
|
||||
Deoptimizer::CALCULATE_ENTRY_ADDRESS);
|
||||
Add(address, "lazy_deopt");
|
||||
}
|
||||
}
|
||||
|
||||
// Add external references provided by the embedder (a null-terminated array).
|
||||
void ExternalReferenceTable::AddApiReferences(Isolate* isolate) {
|
||||
// Add external references provided by the embedder (a null-terminated
|
||||
// array).
|
||||
intptr_t* api_external_references = isolate->api_external_references();
|
||||
if (api_external_references != nullptr) {
|
||||
while (*api_external_references != 0) {
|
||||
|
@ -40,6 +40,16 @@ class ExternalReferenceTable {
|
||||
refs_.Add(entry);
|
||||
}
|
||||
|
||||
void AddReferences(Isolate* isolate);
|
||||
void AddBuiltins(Isolate* isolate);
|
||||
void AddRuntimeFunctions(Isolate* isolate);
|
||||
void AddStatCounters(Isolate* isolate);
|
||||
void AddIsolateAddresses(Isolate* isolate);
|
||||
void AddAccessors(Isolate* isolate);
|
||||
void AddStubCache(Isolate* isolate);
|
||||
void AddDeoptEntries(Isolate* isolate);
|
||||
void AddApiReferences(Isolate* isolate);
|
||||
|
||||
List<ExternalReferenceEntry> refs_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ExternalReferenceTable);
|
||||
|
Loading…
Reference in New Issue
Block a user