Ignore:
Timestamp:
May 24, 2010, 11:46:49 AM (15 years ago)
Author:
[email protected]
Message:

https://bugs.webkit.org/show_bug.cgi?id=39583
Move creation of 'this' object from caller to callee in construction.

Reviewed by Sam Weinig.

Presently the caller of a constructor is responsible for providing a this
object. Instead, move the object creation into a new op_create_this opcode,
planted in the head of the contructor bytecode for a function. Since the
prototype for the object is provided by performing a get_by_id on the callee,
also add a new get_callee opcode (this is used to get the callee JSFunction
into a register so that a normal get_by_id can be used).

Currently the caller is also responsible for detecting when op_construct is
performed on a JSFunction representing a host function, in which case an
exception is thrown – and this check currently takes place when constructing
the this object. Instead, mirroring the recent changes for non-host functions,
add a parallel code-path for native constructors to follow, with a thunk for
invoking native constructors provided by JITStubs, and a constructor-specific
NativeFunction on NativeExecutable. Provide an implementation of a host
constructor which will throw an exception.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):
(JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset):

  • bytecode/CodeBlock.h:
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitConstruct):

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::emitGetByIdExceptionInfo):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

  • jit/JITCall32_64.cpp:

(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):
(JSC::JIT::privateCompileCTINativeCall):
(JSC::JIT::emit_op_neq_null):
(JSC::JIT::emit_op_convert_this):
(JSC::JIT::emit_op_get_callee):
(JSC::JIT::emit_op_create_this):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):
(JSC::JIT::privateCompileCTINativeCall):
(JSC::JIT::emit_op_get_callee):
(JSC::JIT::emit_op_create_this):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):
(JSC::JITThunks::hostFunctionStub):

  • jit/JITStubs.h:

(JSC::JITThunks::ctiNativeConstruct):
(JSC::):

  • runtime/ExceptionHelpers.cpp:

(JSC::createNotAnObjectError):

  • runtime/Executable.h:

(JSC::NativeExecutable::create):
(JSC::NativeExecutable::NativeExecutable):

  • runtime/JSFunction.cpp:

(JSC::callHostFunctionAsConstructor):

  • runtime/JSFunction.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r59980 r60075  
    38403840        vPC = callFrame->returnPC();
    38413841        callFrame = callFrame->callerFrame();
     3842        codeBlock = callFrame->codeBlock();
    38423843       
    38433844        if (callFrame->hasHostCallFrameFlag())
     
    38843885        vPC = callFrame->returnPC();
    38853886        callFrame = callFrame->callerFrame();
     3887        codeBlock = callFrame->codeBlock();
    38863888       
    38873889        if (callFrame->hasHostCallFrameFlag())
     
    39293931
    39303932        vPC += OPCODE_LENGTH(op_enter_with_activation);
     3933        NEXT_INSTRUCTION();
     3934    }
     3935    DEFINE_OPCODE(op_get_callee) {
     3936        /* op_get_callee callee(r)
     3937
     3938           Move callee into a register.
     3939        */
     3940
     3941        callFrame->r(vPC[1].u.operand) = callFrame->callee();
     3942
     3943        vPC += OPCODE_LENGTH(op_get_callee);
     3944        NEXT_INSTRUCTION();
     3945    }
     3946    DEFINE_OPCODE(op_create_this) {
     3947        /* op_create_this this(r) proto(r)
     3948
     3949           Allocate an object as 'this', fr use in construction.
     3950
     3951           This opcode should only be used at the beginning of a code
     3952           block.
     3953        */
     3954
     3955        int thisRegister = vPC[1].u.operand;
     3956        int protoRegister = vPC[2].u.operand;
     3957
     3958        JSFunction* constructor = asFunction(callFrame->callee());
     3959#if !ASSERT_DISABLED
     3960        ConstructData constructData;
     3961        ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
     3962#endif
     3963
     3964        Structure* structure;
     3965        JSValue proto = callFrame->r(protoRegister).jsValue();
     3966        if (proto.isObject())
     3967            structure = asObject(proto)->inheritorID();
     3968        else
     3969            structure = constructor->scope().node()->globalObject->emptyObjectStructure();
     3970        callFrame->r(thisRegister) = new (&callFrame->globalData()) JSObject(structure);
     3971
     3972        vPC += OPCODE_LENGTH(op_create_this);
    39313973        NEXT_INSTRUCTION();
    39323974    }
     
    40014043        int argCount = vPC[2].u.operand;
    40024044        int registerOffset = vPC[3].u.operand;
    4003         int proto = vPC[4].u.operand;
    4004         int thisRegister = vPC[5].u.operand;
    40054045
    40064046        JSValue v = callFrame->r(func).jsValue();
     
    40124052            ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
    40134053            CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain);
    4014 
    4015             Structure* structure;
    4016             JSValue prototype = callFrame->r(proto).jsValue();
    4017             if (prototype.isObject())
    4018                 structure = asObject(prototype)->inheritorID();
    4019             else
    4020                 structure = callDataScopeChain->globalObject->emptyObjectStructure();
    4021             JSObject* newObject = new (globalData) JSObject(structure);
    4022 
    4023             callFrame->r(thisRegister) = JSValue(newObject); // "this" value
    40244054
    40254055            CallFrame* previousCallFrame = callFrame;
     
    40444074
    40454075        if (constructType == ConstructTypeHost) {
    4046             ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
    4047 
    40484076            ScopeChainNode* scopeChain = callFrame->scopeChain();
    40494077            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
    40504078            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, 0, argCount, 0);
     4079
     4080            Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
     4081            ArgList args(thisRegister + 1, argCount - 1);
    40514082
    40524083            JSValue returnValue;
Note: See TracChangeset for help on using the changeset viewer.