Commit 623e8021 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [es6] Introduce spec compliant IsConstructor.

Port 8fe3ac07

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}
parent aa30d4e2
......@@ -1657,6 +1657,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 -------------
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment