Chromium Code Reviews| 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()), |
|
Michael Starzinger
2016/03/22 12:54:31
Note that checking like this will not cover mutabl
Benedikt Meurer
2016/03/22 13:01:18
As discussed offline, this is in line with what we
|
| + &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) \ |
|
Michael Starzinger
2016/03/22 12:54:31
All four macros seem to do the same. Is there a re
Benedikt Meurer
2016/03/22 13:01:18
Different parameters and for symmetry.
|
| + 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 |