| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index adb0340023bc885c8c69e044605722e124177ce0..82eca8c1f11ac8e86154e26c8e7961e25f53da81 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -9,6 +9,8 @@
|
| #include "src/api-natives.h"
|
| #include "src/base/once.h"
|
| #include "src/bootstrapper.h"
|
| +#include "src/code-factory.h"
|
| +#include "src/compiler/code-stub-assembler.h"
|
| #include "src/dateparser-inl.h"
|
| #include "src/elements.h"
|
| #include "src/frames-inl.h"
|
| @@ -2012,6 +2014,81 @@ BUILTIN(MathImul) {
|
| return *isolate->factory()->NewNumberFromInt(product);
|
| }
|
|
|
| +// ES6 section 20.2.2.32 Math.sqrt ( x )
|
| +void Builtins::Generate_MathSqrt(compiler::CodeStubAssembler* assembler) {
|
| + typedef compiler::CodeStubAssembler::Label Label;
|
| + typedef compiler::Node Node;
|
| + typedef compiler::CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* context = assembler->Parameter(4);
|
| +
|
| + // Shared entry for the floating point sqrt.
|
| + Label do_fsqrt(assembler);
|
| + Variable var_fsqrt_x(assembler, MachineRepresentation::kFloat64);
|
| +
|
| + // We might need to loop once due to the ToNumber conversion.
|
| + Variable var_x(assembler, MachineRepresentation::kTagged);
|
| + Label loop(assembler, &var_x);
|
| + var_x.Bind(assembler->Parameter(1));
|
| + assembler->Goto(&loop);
|
| + assembler->Bind(&loop);
|
| + {
|
| + // Load the current {x} value.
|
| + Node* x = var_x.value();
|
| +
|
| + // Check if {x} is a Smi or a HeapObject.
|
| + Label if_xissmi(assembler), if_xisnotsmi(assembler);
|
| + assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
|
| +
|
| + assembler->Bind(&if_xissmi);
|
| + {
|
| + // Perform the floating point sqrt.
|
| + var_fsqrt_x.Bind(assembler->SmiToFloat64(x));
|
| + assembler->Goto(&do_fsqrt);
|
| + }
|
| +
|
| + assembler->Bind(&if_xisnotsmi);
|
| + {
|
| + // Load the map of {x}.
|
| + Node* x_map = assembler->LoadMap(x);
|
| +
|
| + // Check if {x} is a HeapNumber.
|
| + Label if_xisnumber(assembler),
|
| + if_xisnotnumber(assembler, Label::kDeferred);
|
| + assembler->Branch(
|
| + assembler->WordEqual(x_map, assembler->HeapNumberMapConstant()),
|
| + &if_xisnumber, &if_xisnotnumber);
|
| +
|
| + assembler->Bind(&if_xisnumber);
|
| + {
|
| + // Perform the floating point sqrt.
|
| + var_fsqrt_x.Bind(assembler->LoadHeapNumberValue(x));
|
| + assembler->Goto(&do_fsqrt);
|
| + }
|
| +
|
| + assembler->Bind(&if_xisnotnumber);
|
| + {
|
| + // Convert {x} to a Number first.
|
| + Callable callable =
|
| + CodeFactory::NonNumberToNumber(assembler->isolate());
|
| + var_x.Bind(assembler->CallStub(callable, context, x));
|
| + assembler->Goto(&loop);
|
| + }
|
| + }
|
| + }
|
| +
|
| + assembler->Bind(&do_fsqrt);
|
| + {
|
| + Node* x = var_fsqrt_x.value();
|
| + Node* value = assembler->Float64Sqrt(x);
|
| + Node* result = assembler->Allocate(HeapNumber::kSize,
|
| + compiler::CodeStubAssembler::kNone);
|
| + assembler->StoreMapNoWriteBarrier(result,
|
| + assembler->HeapNumberMapConstant());
|
| + assembler->StoreHeapNumberValue(result, value);
|
| + assembler->Return(result);
|
| + }
|
| +}
|
|
|
| // -----------------------------------------------------------------------------
|
| // ES6 section 26.1 The Reflect Object
|
| @@ -4275,12 +4352,14 @@ Address const Builtins::c_functions_[cfunction_count] = {
|
|
|
|
|
| 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;
|
| BuiltinExtraArguments extra_args;
|
| + int argc;
|
| };
|
|
|
| #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
|
| @@ -4298,8 +4377,60 @@ class BuiltinFunctionTable {
|
| friend class Builtins;
|
| };
|
|
|
| -static BuiltinFunctionTable builtin_function_table =
|
| - BUILTIN_FUNCTION_TABLE_INIT;
|
| +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;
|
| +#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, BuiltinExtraArguments);
|
| + 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.
|
| + DCHECK(!masm.has_frame());
|
| + g(&masm, builtin_desc->name, builtin_desc->extra_args);
|
| + // Move the code into the object heap.
|
| + CodeDesc desc;
|
| + masm.GetCode(&desc);
|
| + Code::Flags flags = builtin_desc->flags;
|
| + return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
|
| +}
|
| +
|
| +Handle<Code> CodeStubAssemblerBuilder(Isolate* isolate,
|
| + BuiltinDesc const* builtin_desc) {
|
| + Zone zone;
|
| + compiler::CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
|
| + builtin_desc->flags,
|
| + builtin_desc->s_name);
|
| + // Generate the code/adaptor.
|
| + typedef void (*Generator)(compiler::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
|
| @@ -4307,47 +4438,70 @@ static BuiltinFunctionTable builtin_function_table =
|
| // Code::Flags names a non-abstract type.
|
| void Builtins::InitBuiltinFunctionTable() {
|
| BuiltinDesc* functions = builtin_function_table.functions_;
|
| - functions[builtin_count].generator = NULL;
|
| - functions[builtin_count].c_code = NULL;
|
| - functions[builtin_count].s_name = NULL;
|
| + 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].extra_args = BuiltinExtraArguments::kNone;
|
| + functions[builtin_count].argc = 0;
|
|
|
| #define DEF_FUNCTION_PTR_C(aname, aextra_args) \
|
| + functions->builder = &MacroAssemblerBuilder; \
|
| functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
|
| functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
|
| functions->s_name = #aname; \
|
| functions->name = c_##aname; \
|
| functions->flags = Code::ComputeFlags(Code::BUILTIN); \
|
| functions->extra_args = BuiltinExtraArguments::aextra_args; \
|
| + functions->argc = 0; \
|
| ++functions;
|
|
|
| #define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
|
| + functions->builder = &MacroAssemblerBuilder; \
|
| functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| functions->c_code = NULL; \
|
| functions->s_name = #aname; \
|
| functions->name = k##aname; \
|
| functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
|
| functions->extra_args = BuiltinExtraArguments::kNone; \
|
| + functions->argc = 0; \
|
| + ++functions;
|
| +
|
| +#define DEF_FUNCTION_PTR_T(aname, aargc) \
|
| + functions->builder = &CodeStubAssemblerBuilder; \
|
| + functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| + functions->c_code = NULL; \
|
| + functions->s_name = #aname; \
|
| + functions->name = k##aname; \
|
| + functions->flags = \
|
| + Code::ComputeFlags(Code::BUILTIN, UNINITIALIZED, kNoExtraICState); \
|
| + functions->extra_args = BuiltinExtraArguments::kNone; \
|
| + functions->argc = aargc; \
|
| ++functions;
|
|
|
| #define DEF_FUNCTION_PTR_H(aname, kind) \
|
| + functions->builder = &MacroAssemblerBuilder; \
|
| functions->generator = FUNCTION_ADDR(Generate_##aname); \
|
| functions->c_code = NULL; \
|
| functions->s_name = #aname; \
|
| functions->name = k##aname; \
|
| functions->flags = Code::ComputeHandlerFlags(Code::kind); \
|
| functions->extra_args = BuiltinExtraArguments::kNone; \
|
| + functions->argc = 0; \
|
| ++functions;
|
|
|
| BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
|
| BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
|
| + BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
|
| BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
|
| BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
|
|
|
| #undef DEF_FUNCTION_PTR_C
|
| #undef DEF_FUNCTION_PTR_A
|
| +#undef DEF_FUNCTION_PTR_H
|
| +#undef DEF_FUNCTION_PTR_T
|
| }
|
|
|
|
|
| @@ -4359,40 +4513,11 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
|
|
|
| const BuiltinDesc* functions = builtin_function_table.functions();
|
|
|
| - // 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;
|
| -#endif
|
| - union { int force_alignment; byte buffer[buffer_size]; } u;
|
| -
|
| // 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) {
|
| - MacroAssembler masm(isolate, u.buffer, sizeof u.buffer,
|
| - CodeObjectRequired::kYes);
|
| - // Generate the code/adaptor.
|
| - typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
|
| - Generator g = FUNCTION_CAST<Generator>(functions[i].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.
|
| - DCHECK(!masm.has_frame());
|
| - g(&masm, functions[i].name, functions[i].extra_args);
|
| - // Move the code into the object heap.
|
| - CodeDesc desc;
|
| - masm.GetCode(&desc);
|
| - Code::Flags flags = functions[i].flags;
|
| - Handle<Code> code =
|
| - isolate->factory()->NewCode(desc, flags, masm.CodeObject());
|
| + Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
|
| // Log the event and add the code to the builtins array.
|
| PROFILE(isolate,
|
| CodeCreateEvent(Logger::BUILTIN_TAG, AbstractCode::cast(*code),
|
| @@ -4466,6 +4591,11 @@ Handle<Code> Builtins::name() { \
|
| reinterpret_cast<Code**>(builtin_address(k##name)); \
|
| return Handle<Code>(code_address); \
|
| }
|
| +#define DEFINE_BUILTIN_ACCESSOR_T(name, argc) \
|
| + Handle<Code> Builtins::name() { \
|
| + Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
|
| + return Handle<Code>(code_address); \
|
| + }
|
| #define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
|
| Handle<Code> Builtins::name() { \
|
| Code** code_address = \
|
| @@ -4474,11 +4604,13 @@ Handle<Code> Builtins::name() { \
|
| }
|
| BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
|
| BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
|
| +BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
|
| BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
|
| BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
|
| #undef DEFINE_BUILTIN_ACCESSOR_C
|
| #undef DEFINE_BUILTIN_ACCESSOR_A
|
| -
|
| +#undef DEFINE_BUILTIN_ACCESSOR_T
|
| +#undef DEFINE_BUILTIN_ACCESSOR_H
|
|
|
| } // namespace internal
|
| } // namespace v8
|
|
|