Index: src/builtins/builtins.cc |
diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc |
index 71aacb6affe519e18f70dfaa743491fbb912c1ce..4c9721ae68ef944a10894c12481e722cc048f3d0 100644 |
--- a/src/builtins/builtins.cc |
+++ b/src/builtins/builtins.cc |
@@ -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_; |
+namespace { |
+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 |
+} |
- base::OnceType once_; |
- BuiltinDesc functions_[Builtins::builtin_count + 1]; |
- |
- friend class Builtins; |
-}; |
- |
-namespace { |
+typedef void (*MacroAssemblerGenerator)(MacroAssembler*); |
+typedef void (*CodeAssemblerGenerator)(CodeStubAssembler*); |
-BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT; |
+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()); |
+ generator(&masm); |
+ CodeDesc desc; |
+ masm.GetCode(&desc); |
+ Handle<Code> code = |
+ isolate->factory()->NewCode(desc, flags, masm.CodeObject()); |
+ PostBuildProfileAndTracing(isolate, *code, s_name); |
+ return *code; |
+} |
-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. |
+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; |
-#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; |
-#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. |
+ 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. |
+ Builtins::Generate_Adaptor(&masm, builtin_address, exit_frame_type); |
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, 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 |
- |
- const BuiltinDesc* functions = builtin_function_table.functions(); |
- |
- // 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; |
+ 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; |
+ |
+ BUILTIN_LIST(BUILD_CPP, BUILD_API, BUILD_TFJ, BUILD_TFS, BUILD_ASM, |
+ BUILD_ASH, BUILD_ASM); |
+ |
+#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); |
} |