diff options
Diffstat (limited to 'deps/v8/src/ppc/builtins-ppc.cc')
-rw-r--r-- | deps/v8/src/ppc/builtins-ppc.cc | 317 |
1 files changed, 196 insertions, 121 deletions
diff --git a/deps/v8/src/ppc/builtins-ppc.cc b/deps/v8/src/ppc/builtins-ppc.cc index e08c865e4e..9b3a3fb9ad 100644 --- a/deps/v8/src/ppc/builtins-ppc.cc +++ b/deps/v8/src/ppc/builtins-ppc.cc @@ -21,11 +21,12 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id, BuiltinExtraArguments extra_args) { // ----------- S t a t e ------------- // -- r3 : number of arguments excluding receiver - // -- r4 : called function (only guaranteed when - // extra_args requires it) + // (only guaranteed when the called function + // is not marked as DontAdaptArguments) + // -- r4 : called function // -- sp[0] : last argument // -- ... - // -- sp[4 * (argc - 1)] : first argument (argc == r0) + // -- sp[4 * (argc - 1)] : first argument // -- sp[4 * argc] : receiver // ----------------------------------- __ AssertFunction(r4); @@ -46,9 +47,27 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id, DCHECK(extra_args == NO_EXTRA_ARGUMENTS); } - // JumpToExternalReference expects r0 to contain the number of arguments - // including the receiver and the extra arguments. + // JumpToExternalReference expects r3 to contain the number of arguments + // including the receiver and the extra arguments. But r3 is only valid + // if the called function is marked as DontAdaptArguments, otherwise we + // need to load the argument count from the SharedFunctionInfo. + __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); + __ LoadWordArith( + r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); +#if !V8_TARGET_ARCH_PPC64 + __ SmiUntag(r5); +#endif + __ cmpi(r5, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); + if (CpuFeatures::IsSupported(ISELECT)) { + __ isel(ne, r3, r5, r3); + } else { + Label skip; + __ beq(&skip); + __ mr(r3, r5); + __ bind(&skip); + } __ addi(r3, r3, Operand(num_extra_args + 1)); + __ JumpToExternalReference(ExternalReference(id, masm->isolate())); } @@ -60,7 +79,8 @@ static void GenerateLoadInternalArrayFunction(MacroAssembler* masm, __ LoadP(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); - __ LoadP(result, FieldMemOperand(result, GlobalObject::kNativeContextOffset)); + __ LoadP(result, + FieldMemOperand(result, JSGlobalObject::kNativeContextOffset)); // Load the InternalArray function from the native context. __ LoadP(result, MemOperand(result, Context::SlotOffset( @@ -74,7 +94,8 @@ static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { __ LoadP(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); - __ LoadP(result, FieldMemOperand(result, GlobalObject::kNativeContextOffset)); + __ LoadP(result, + FieldMemOperand(result, JSGlobalObject::kNativeContextOffset)); // Load the Array function from the native context. __ LoadP( result, @@ -201,41 +222,44 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r3 : number of arguments // -- r4 : constructor function + // -- r6 : original constructor // -- lr : return address // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) // -- sp[argc * 4] : receiver // ----------------------------------- - // 1. Load the first argument into r3 and get rid of the rest (including the + // 1. Load the first argument into r5 and get rid of the rest (including the // receiver). { Label no_arguments, done; __ cmpi(r3, Operand::Zero()); __ beq(&no_arguments); __ subi(r3, r3, Operand(1)); - __ ShiftLeftImm(r3, r3, Operand(kPointerSizeLog2)); - __ LoadPUX(r3, MemOperand(sp, r3)); + __ ShiftLeftImm(r5, r3, Operand(kPointerSizeLog2)); + __ LoadPUX(r5, MemOperand(sp, r5)); __ Drop(2); __ b(&done); __ bind(&no_arguments); - __ LoadRoot(r3, Heap::kempty_stringRootIndex); + __ LoadRoot(r5, Heap::kempty_stringRootIndex); __ Drop(1); __ bind(&done); } - // 2. Make sure r3 is a string. + // 2. Make sure r5 is a string. { Label convert, done_convert; - __ JumpIfSmi(r3, &convert); - __ CompareObjectType(r3, r5, r5, FIRST_NONSTRING_TYPE); + __ JumpIfSmi(r5, &convert); + __ CompareObjectType(r5, r7, r7, FIRST_NONSTRING_TYPE); __ blt(&done_convert); __ bind(&convert); { FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); ToStringStub stub(masm->isolate()); - __ push(r4); + __ Push(r4, r6); + __ mr(r3, r5); __ CallStub(&stub); - __ pop(r4); + __ mr(r5, r3); + __ Pop(r4, r6); } __ bind(&done_convert); } @@ -243,13 +267,18 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { // 3. Allocate a JSValue wrapper for the string. { // ----------- S t a t e ------------- - // -- r3 : the first argument + // -- r5 : the first argument // -- r4 : constructor function + // -- r6 : original constructor // -- lr : return address // ----------------------------------- - Label allocate, done_allocate; - __ mr(r5, r3); + Label allocate, done_allocate, rt_call; + + // Fall back to runtime if the original constructor and function differ. + __ cmp(r4, r6); + __ bne(&rt_call); + __ Allocate(JSValue::kSize, r3, r6, r7, &allocate, TAG_OBJECT); __ bind(&done_allocate); @@ -273,6 +302,17 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { __ Pop(r4, r5); } __ b(&done_allocate); + + // Fallback to the runtime to create new object. + __ bind(&rt_call); + { + FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); + __ Push(r4, r5, r4, r6); // constructor function, original constructor + __ CallRuntime(Runtime::kNewObject, 2); + __ Pop(r4, r5); + } + __ StoreP(r5, FieldMemOperand(r3, JSValue::kValueOffset), r0); + __ Ret(); } } @@ -356,18 +396,24 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ cmpi(r5, Operand::Zero()); __ bne(&rt_call); - // Fall back to runtime if the original constructor and function differ. - __ cmp(r4, r6); + // Verify that the original constructor is a JSFunction. + __ CompareObjectType(r6, r8, r7, JS_FUNCTION_TYPE); __ bne(&rt_call); // Load the initial map and verify that it is in fact a map. - // r4: constructor function + // r6: original constructor __ LoadP(r5, - FieldMemOperand(r4, JSFunction::kPrototypeOrInitialMapOffset)); + FieldMemOperand(r6, JSFunction::kPrototypeOrInitialMapOffset)); __ JumpIfSmi(r5, &rt_call); __ CompareObjectType(r5, r8, r7, MAP_TYPE); __ bne(&rt_call); + // Fall back to runtime if the expected base constructor and base + // constructor differ. + __ LoadP(r8, FieldMemOperand(r5, Map::kConstructorOrBackPointerOffset)); + __ cmp(r4, r8); + __ bne(&rt_call); + // Check that the constructor is not constructing a JSFunction (see // comments in Runtime_NewObject in runtime.cc). In which case the // initial map's instance type would be JS_FUNCTION_TYPE. @@ -390,9 +436,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ cmpi(r11, Operand(Map::kSlackTrackingCounterEnd)); __ bne(&allocate); - __ push(r4); - - __ Push(r5, r4); // r4 = constructor + __ Push(r4, r5, r5); // r5 = initial map __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); __ Pop(r4, r5); @@ -488,7 +532,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // r4: constructor function // r6: original constructor __ bind(&rt_call); - __ Push(r4, r6); + __ Push(r4, r6); // constructor function, original constructor __ CallRuntime(Runtime::kNewObject, 2); __ mr(r7, r3); @@ -885,21 +929,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { // - Support profiler (specifically profiling_counter). // - Call ProfileEntryHookStub when isolate has a function_entry_hook. // - Allow simulator stop operations if FLAG_stop_at is set. - // - Deal with sloppy mode functions which need to replace the - // receiver with the global proxy when called as functions (without an - // explicit receiver object). // - Code aging of the BytecodeArray object. - // - Supporting FLAG_trace. - // - // The following items are also not done here, and will probably be done using - // explicit bytecodes instead: - // - Allocating a new local context if applicable. - // - Setting up a local binding to the this function, which is used in - // derived constructors with super calls. - // - Setting new.target if required. - // - Dealing with REST parameters (only if - // https://codereview.chromium.org/1235153006 doesn't land by then). - // - Dealing with argument objects. // Perform stack guard check. { @@ -907,7 +937,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { __ LoadRoot(r0, Heap::kStackLimitRootIndex); __ cmp(sp, r0); __ bge(&ok); + __ push(kInterpreterBytecodeArrayRegister); __ CallRuntime(Runtime::kStackGuard, 0); + __ pop(kInterpreterBytecodeArrayRegister); __ bind(&ok); } @@ -956,6 +988,63 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { } +static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index, + Register count, Register scratch) { + Label loop; + __ addi(index, index, Operand(kPointerSize)); // Bias up for LoadPU + __ mtctr(count); + __ bind(&loop); + __ LoadPU(scratch, MemOperand(index, -kPointerSize)); + __ push(scratch); + __ bdnz(&loop); +} + + +// static +void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- r3 : the number of arguments (not including the receiver) + // -- r5 : the address of the first argument to be pushed. Subsequent + // arguments should be consecutive above this, in the same order as + // they are to be pushed onto the stack. + // -- r4 : the target to call (can be any Object). + // ----------------------------------- + + // Calculate number of arguments (add one for receiver). + __ addi(r6, r3, Operand(1)); + + // Push the arguments. + Generate_InterpreterPushArgs(masm, r5, r6, r7); + + // Call the target. + __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); +} + + +// static +void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- r3 : argument count (not including receiver) + // -- r6 : original constructor + // -- r4 : constructor to call + // -- r5 : address of the first argument + // ----------------------------------- + + // Push a slot for the receiver to be constructed. + __ push(r3); + + // Push the arguments (skip if none). + Label skip; + __ cmpi(r3, Operand::Zero()); + __ beq(&skip); + Generate_InterpreterPushArgs(masm, r5, r3, r7); + __ bind(&skip); + + // Call the constructor with r3, r4, and r6 unmodified. + __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL); +} + + void Builtins::Generate_CompileLazy(MacroAssembler* masm) { CallRuntimePassFunction(masm, Runtime::kCompileLazy); GenerateTailCallToReturnedCode(masm); @@ -1499,71 +1588,80 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { // static -void Builtins::Generate_CallFunction(MacroAssembler* masm) { +void Builtins::Generate_CallFunction(MacroAssembler* masm, + ConvertReceiverMode mode) { // ----------- S t a t e ------------- // -- r3 : the number of arguments (not including the receiver) // -- r4 : the function to call (checked to be a JSFunction) // ----------------------------------- - - Label convert, convert_global_proxy, convert_to_object, done_convert; __ AssertFunction(r4); - // TODO(bmeurer): Throw a TypeError if function's [[FunctionKind]] internal - // slot is "classConstructor". + + // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) + // Check that the function is not a "classConstructor". + Label class_constructor; + __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); + __ lwz(r6, FieldMemOperand(r5, SharedFunctionInfo::kCompilerHintsOffset)); + __ TestBitMask(r6, SharedFunctionInfo::kClassConstructorBits, r0); + __ bne(&class_constructor, cr0); + // Enter the context of the function; ToObject has to run in the function // context, and we also need to take the global proxy from the function // context in case of conversion. - // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) - STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == - SharedFunctionInfo::kStrictModeByteOffset); __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); - __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); // We need to convert the receiver for non-native sloppy mode functions. - __ lbz(r6, FieldMemOperand(r5, SharedFunctionInfo::kNativeByteOffset)); - __ andi(r0, r6, Operand((1 << SharedFunctionInfo::kNativeBitWithinByte) | - (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); + Label done_convert; + __ andi(r0, r6, Operand((1 << SharedFunctionInfo::kStrictModeBit) | + (1 << SharedFunctionInfo::kNativeBit))); __ bne(&done_convert, cr0); { - __ ShiftLeftImm(r6, r3, Operand(kPointerSizeLog2)); - __ LoadPX(r6, MemOperand(sp, r6)); - // ----------- S t a t e ------------- // -- r3 : the number of arguments (not including the receiver) // -- r4 : the function to call (checked to be a JSFunction) // -- r5 : the shared function info. - // -- r6 : the receiver // -- cp : the function context. // ----------------------------------- - Label convert_receiver; - __ JumpIfSmi(r6, &convert_to_object); - STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); - __ CompareObjectType(r6, r7, r7, FIRST_JS_RECEIVER_TYPE); - __ bge(&done_convert); - __ JumpIfRoot(r6, Heap::kUndefinedValueRootIndex, &convert_global_proxy); - __ JumpIfNotRoot(r6, Heap::kNullValueRootIndex, &convert_to_object); - __ bind(&convert_global_proxy); - { + if (mode == ConvertReceiverMode::kNullOrUndefined) { // Patch receiver to global proxy. __ LoadGlobalProxy(r6); + } else { + Label convert_to_object, convert_receiver; + __ ShiftLeftImm(r6, r3, Operand(kPointerSizeLog2)); + __ LoadPX(r6, MemOperand(sp, r6)); + __ JumpIfSmi(r6, &convert_to_object); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CompareObjectType(r6, r7, r7, FIRST_JS_RECEIVER_TYPE); + __ bge(&done_convert); + if (mode != ConvertReceiverMode::kNotNullOrUndefined) { + Label convert_global_proxy; + __ JumpIfRoot(r6, Heap::kUndefinedValueRootIndex, + &convert_global_proxy); + __ JumpIfNotRoot(r6, Heap::kNullValueRootIndex, &convert_to_object); + __ bind(&convert_global_proxy); + { + // Patch receiver to global proxy. + __ LoadGlobalProxy(r6); + } + __ b(&convert_receiver); + } + __ bind(&convert_to_object); + { + // Convert receiver using ToObject. + // TODO(bmeurer): Inline the allocation here to avoid building the frame + // in the fast case? (fall back to AllocateInNewSpace?) + FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); + __ SmiTag(r3); + __ Push(r3, r4); + __ mr(r3, r6); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); + __ mr(r6, r3); + __ Pop(r3, r4); + __ SmiUntag(r3); + } + __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); + __ bind(&convert_receiver); } - __ b(&convert_receiver); - __ bind(&convert_to_object); - { - // Convert receiver using ToObject. - // TODO(bmeurer): Inline the allocation here to avoid building the frame - // in the fast case? (fall back to AllocateInNewSpace?) - FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); - __ SmiTag(r3); - __ Push(r3, r4); - __ mr(r3, r6); - ToObjectStub stub(masm->isolate()); - __ CallStub(&stub); - __ mr(r6, r3); - __ Pop(r3, r4); - __ SmiUntag(r3); - } - __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); - __ bind(&convert_receiver); __ ShiftLeftImm(r7, r3, Operand(kPointerSizeLog2)); __ StorePX(r6, MemOperand(sp, r7)); } @@ -1585,11 +1683,18 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm) { ParameterCount actual(r3); ParameterCount expected(r5); __ InvokeCode(r6, expected, actual, JUMP_FUNCTION, NullCallWrapper()); + + // The function is a "classConstructor", need to raise an exception. + __ bind(&class_constructor); + { + FrameAndConstantPoolScope frame(masm, StackFrame::INTERNAL); + __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); + } } // static -void Builtins::Generate_Call(MacroAssembler* masm) { +void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { // ----------- S t a t e ------------- // -- r3 : the number of arguments (not including the receiver) // -- r4 : the target to call (can be any Object). @@ -1599,8 +1704,8 @@ void Builtins::Generate_Call(MacroAssembler* masm) { __ JumpIfSmi(r4, &non_callable); __ bind(&non_smi); __ CompareObjectType(r4, r7, r8, JS_FUNCTION_TYPE); - __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET, - eq); + __ Jump(masm->isolate()->builtins()->CallFunction(mode), + RelocInfo::CODE_TARGET, eq); __ cmpi(r8, Operand(JS_FUNCTION_PROXY_TYPE)); __ bne(&non_function); @@ -1622,7 +1727,9 @@ void Builtins::Generate_Call(MacroAssembler* masm) { __ StorePX(r4, MemOperand(sp, r8)); // Let the "call_as_function_delegate" take care of the rest. __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, r4); - __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); + __ Jump(masm->isolate()->builtins()->CallFunction( + ConvertReceiverMode::kNotNullOrUndefined), + RelocInfo::CODE_TARGET); // 3. Call to something that is not callable. __ bind(&non_callable); @@ -1719,32 +1826,6 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { } -// static -void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- r3 : the number of arguments (not including the receiver) - // -- r5 : the address of the first argument to be pushed. Subsequent - // arguments should be consecutive above this, in the same order as - // they are to be pushed onto the stack. - // -- r4 : the target to call (can be any Object). - - // Calculate number of arguments (add one for receiver). - __ addi(r6, r3, Operand(1)); - - // Push the arguments. - Label loop; - __ addi(r5, r5, Operand(kPointerSize)); // Bias up for LoadPU - __ mtctr(r6); - __ bind(&loop); - __ LoadPU(r6, MemOperand(r5, -kPointerSize)); - __ push(r6); - __ bdnz(&loop); - - // Call the target. - __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); -} - - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r3 : actual number of arguments @@ -1804,13 +1885,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { Label no_strong_error; __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); __ lwz(r8, FieldMemOperand(r7, SharedFunctionInfo::kCompilerHintsOffset)); - __ TestBit(r8, -#if V8_TARGET_ARCH_PPC64 - SharedFunctionInfo::kStrongModeFunction, -#else - SharedFunctionInfo::kStrongModeFunction + kSmiTagSize, -#endif - r0); + __ TestBit(r8, SharedFunctionInfo::kStrongModeBit, r0); __ beq(&no_strong_error, cr0); // What we really care about is the required number of arguments. |