From 0ffcb5037ea85beee7f2d32114899bc37863fa07 Mon Sep 17 00:00:00 2001 From: mbrandy Date: Wed, 30 Sep 2015 10:01:01 -0700 Subject: [PATCH] PPC: [es6] Introduce spec compliant IsConstructor. Port 8fe3ac07014ce5891be0a1cbd8019e9f3b02ff0b Original commit message: There was already a bit on the Map named "function with prototype", which basically meant that the Map was a map for a JSFunction that could be used as a constructor. Now this CL generalizes that bit to IsConstructor, which says that whatever (Heap)Object you are looking at can be used as a constructor (i.e. the bit is also set for bound functions that can be used as constructors and proxies that have a [[Construct]] internal method). This way we have a single chokepoint for IsConstructor checking, which allows us to get rid of the various ways in which we tried to guess whether something could be used as a constructor or not. Drive-by-fix: Renamed IsConstructor on FunctionKind to IsClassConstructor to resolve the weird name clash, and the IsClassConstructor name also matches the spec. R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, dstence@us.ibm.com BUG=v8:4413, v8:4430 LOG=n Review URL: https://codereview.chromium.org/1382673002 Cr-Commit-Position: refs/heads/master@{#31027} --- src/ppc/builtins-ppc.cc | 65 ++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc index b9afc27..e08c865 100644 --- a/src/ppc/builtins-ppc.cc +++ b/src/ppc/builtins-ppc.cc @@ -1658,6 +1658,21 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // static +void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- r3 : the number of arguments (not including the receiver) + // -- r4 : the constructor to call (checked to be a JSFunctionProxy) + // -- r6 : the original constructor (either the same as the constructor or + // the JSFunction on which new was invoked initially) + // ----------------------------------- + + // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies. + __ LoadP(r4, FieldMemOperand(r4, JSFunctionProxy::kConstructTrapOffset)); + __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); +} + + +// static void Builtins::Generate_Construct(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r3 : the number of arguments (not including the receiver) @@ -1666,36 +1681,36 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { // the JSFunction on which new was invoked initially) // ----------------------------------- - Label non_callable, non_function; - __ JumpIfSmi(r4, &non_callable); - __ CompareObjectType(r4, r7, r8, JS_FUNCTION_TYPE); + // Check if target has a [[Construct]] internal method. + Label non_constructor; + __ JumpIfSmi(r4, &non_constructor); + __ LoadP(r7, FieldMemOperand(r4, HeapObject::kMapOffset)); + __ lbz(r5, FieldMemOperand(r7, Map::kBitFieldOffset)); + __ TestBit(r5, Map::kIsConstructor, r0); + __ beq(&non_constructor, cr0); + + // Dispatch based on instance type. + __ CompareInstanceType(r7, r8, JS_FUNCTION_TYPE); __ Jump(masm->isolate()->builtins()->ConstructFunction(), RelocInfo::CODE_TARGET, eq); __ cmpi(r8, Operand(JS_FUNCTION_PROXY_TYPE)); - __ bne(&non_function); - - // 1. Construct of function proxy. - // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies. - __ LoadP(r4, FieldMemOperand(r4, JSFunctionProxy::kConstructTrapOffset)); - __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); + __ Jump(masm->isolate()->builtins()->ConstructProxy(), RelocInfo::CODE_TARGET, + eq); - // 2. Construct of something that else, which might have a [[Construct]] - // internal method (if not we raise an exception). - __ bind(&non_function); - // Check if target has a [[Call]] internal method. - // TODO(bmeurer): This shoud use IsConstructor once available. - __ lbz(r7, FieldMemOperand(r7, Map::kBitFieldOffset)); - __ TestBit(r7, Map::kIsCallable, r0); - __ beq(&non_callable, cr0); - // Overwrite the original receiver the (original) target. - __ ShiftLeftImm(r8, r3, Operand(kPointerSizeLog2)); - __ StorePX(r4, MemOperand(sp, r8)); - // Let the "call_as_constructor_delegate" take care of the rest. - __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, r4); - __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); + // Called Construct on an exotic Object with a [[Construct]] internal method. + { + // Overwrite the original receiver with the (original) target. + __ ShiftLeftImm(r8, r3, Operand(kPointerSizeLog2)); + __ StorePX(r4, MemOperand(sp, r8)); + // Let the "call_as_constructor_delegate" take care of the rest. + __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, r4); + __ Jump(masm->isolate()->builtins()->CallFunction(), + RelocInfo::CODE_TARGET); + } - // 3. Construct of something that is not callable. - __ bind(&non_callable); + // Called Construct on an Object that doesn't have a [[Construct]] internal + // method. + __ bind(&non_constructor); { FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); __ Push(r4); -- 2.7.4