Changeset 206778 in webkit


Ignore:
Timestamp:
Oct 4, 2016 12:31:24 PM (7 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Add a new byte code op_define_property instead of calling defineProperty
https://bugs.webkit.org/show_bug.cgi?id=162108

Reviewed by Saam Barati.

To construct ES6 class, we emitted bytecode that performs the following operations.

  1. construct a new object
  2. put "configurable", "enumerable" etc. fields
  3. call "defineProperty" function

However, this approach has problems. Every time we define a class method, we need to create
a new object to represent property descriptor. This can be removed if we can introduce
a special bytecode or special function.

This patch introduces new bytecodes, op_define_data_property and op_define_accessor_property.
Instead of taking an object, they takes several registers to avoid object allocations.
We're planning to use this bytecode to implement Object.defineProperty in builtin JS next.
This allows us to leverage object allocation sinking. And it also gives us a chance to use
faster ::get and ::hasProperty in JS.

Originally, I attempted to create one bytecode, op_define_property. However, it takes too many
children in DFG and uses so many registers in DFG. This leads tricky program in 32bit platforms.
Furthermore, it does not fit to the number of x64 argument registers. So instead, we introduce
two bytecodes.

And for op_define_accessor_property, we perform CellUse edge filter to getter and setter children.
This edge filter makes us possible to use SpeculateCellOperand and reduce the number of used registers
in comparison with JSValueOperand. To make children Cells even if we do not specify some accessors (for
example, { get: func, set: null } case), we fill registers with special throwTypeErrorFunction.
The attributes bitset keep information like "This property descriptor only has getter slot".

In these two bytecodes, we take attributes (configurable, enumerable, writable, hasGetter etc.) as
register instead of embedding constant int value because we will use these bytecodes to implement
Object.defineProperty next. In Object.defineProperty case, an attributes are not statically defined
at bytecode compiling time.

Run ES6SampleBench/Air 20 times. The result shows ~2% performance improvement.

Baseline:

firstIteration: 84.05 ms +- 4.37 ms
averageWorstCase: 40.54 ms +- 2.81 ms
steadyState: 3317.49 ms +- 48.25 ms
summary: 223.51 ms +- 5.07 ms

Patched:

firstIteration: 84.46 ms +- 4.22 ms
averageWorstCase: 41.48 ms +- 2.33 ms
steadyState: 3253.48 ms +- 29.31 ms
summary: 224.40 ms +- 4.72 ms

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/SpecialPointer.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitMoveLinkTimeConstant):
(JSC::BytecodeGenerator::emitCallDefineProperty):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::BitwiseNotNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):
(JSC::ObjectPatternNode::bindValue):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileDefineDataProperty):
(JSC::DFG::SpeculativeJIT::compileDefineAccessorProperty):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileDefineDataProperty):
(JSC::FTL::DFG::LowerDFGToB3::compileDefineAccessorProperty):
(JSC::FTL::DFG::LowerDFGToB3::compilePutByValWithThis): Deleted.

  • jit/CCallHelpers.cpp:

(JSC::CCallHelpers::setupFourStubArgsGPR): Deleted.

  • jit/CCallHelpers.h:

(JSC::CCallHelpers::setupFourStubArgsGPR):
(JSC::CCallHelpers::setupFiveStubArgsGPR):
(JSC::CCallHelpers::setupArgumentsWithExecState):
(JSC::CCallHelpers::setupStubArgsGPR):
(JSC::CCallHelpers::prepareForTailCallSlow): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_define_data_property):
(JSC::JIT::emit_op_define_accessor_property):

  • llint/LowLevelInterpreter.asm:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:
  • runtime/DefinePropertyAttributes.h: Added.

(JSC::DefinePropertyAttributes::DefinePropertyAttributes):
(JSC::DefinePropertyAttributes::rawRepresentation):
(JSC::DefinePropertyAttributes::hasValue):
(JSC::DefinePropertyAttributes::setValue):
(JSC::DefinePropertyAttributes::hasGet):
(JSC::DefinePropertyAttributes::setGet):
(JSC::DefinePropertyAttributes::hasSet):
(JSC::DefinePropertyAttributes::setSet):
(JSC::DefinePropertyAttributes::writable):
(JSC::DefinePropertyAttributes::configurable):
(JSC::DefinePropertyAttributes::enumerable):
(JSC::DefinePropertyAttributes::setWritable):
(JSC::DefinePropertyAttributes::setConfigurable):
(JSC::DefinePropertyAttributes::setEnumerable):
(JSC::DefinePropertyAttributes::fillWithTriState):
(JSC::DefinePropertyAttributes::extractTriState):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::throwTypeErrorFunction):
(JSC::JSGlobalObject::definePropertyFunction): Deleted.

  • runtime/ObjectConstructor.cpp:

(JSC::ObjectConstructor::addDefineProperty): Deleted.

  • runtime/ObjectConstructor.h:
  • runtime/PropertyDescriptor.h:

(JSC::toPropertyDescriptor):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
40 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r206767 r206778  
     12016-09-27  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] Add a new byte code op_define_property instead of calling defineProperty
     4        https://bugs.webkit.org/show_bug.cgi?id=162108
     5
     6        Reviewed by Saam Barati.
     7
     8        To construct ES6 class, we emitted bytecode that performs the following operations.
     9
     10            1. construct a new object
     11            2. put "configurable", "enumerable" etc. fields
     12            3. call "defineProperty" function
     13
     14        However, this approach has problems. Every time we define a class method, we need to create
     15        a new object to represent property descriptor. This can be removed if we can introduce
     16        a special bytecode or special function.
     17
     18        This patch introduces new bytecodes, op_define_data_property and op_define_accessor_property.
     19        Instead of taking an object, they takes several registers to avoid object allocations.
     20        We're planning to use this bytecode to implement Object.defineProperty in builtin JS next.
     21        This allows us to leverage object allocation sinking. And it also gives us a chance to use
     22        faster ::get and ::hasProperty in JS.
     23
     24        Originally, I attempted to create one bytecode, op_define_property. However, it takes too many
     25        children in DFG and uses so many registers in DFG. This leads tricky program in 32bit platforms.
     26        Furthermore, it does not fit to the number of x64 argument registers. So instead, we introduce
     27        two bytecodes.
     28
     29        And for op_define_accessor_property, we perform CellUse edge filter to getter and setter children.
     30        This edge filter makes us possible to use SpeculateCellOperand and reduce the number of used registers
     31        in comparison with JSValueOperand. To make children Cells even if we do not specify some accessors (for
     32        example, { get: func, set: null } case), we fill registers with special throwTypeErrorFunction.
     33        The attributes bitset keep information like "This property descriptor only has getter slot".
     34
     35        In these two bytecodes, we take attributes (configurable, enumerable, writable, hasGetter etc.) as
     36        register instead of embedding constant int value because we will use these bytecodes to implement
     37        Object.defineProperty next. In Object.defineProperty case, an attributes are not statically defined
     38        at bytecode compiling time.
     39
     40        Run ES6SampleBench/Air 20 times. The result shows ~2% performance improvement.
     41
     42        Baseline:
     43            firstIteration:     84.05 ms +- 4.37 ms
     44            averageWorstCase:   40.54 ms +- 2.81 ms
     45            steadyState:        3317.49 ms +- 48.25 ms
     46            summary:            223.51 ms +- 5.07 ms
     47
     48        Patched:
     49            firstIteration:     84.46 ms +- 4.22 ms
     50            averageWorstCase:   41.48 ms +- 2.33 ms
     51            steadyState:        3253.48 ms +- 29.31 ms
     52            summary:            224.40 ms +- 4.72 ms
     53
     54        * JavaScriptCore.xcodeproj/project.pbxproj:
     55        * bytecode/BytecodeList.json:
     56        * bytecode/BytecodeUseDef.h:
     57        (JSC::computeUsesForBytecodeOffset):
     58        (JSC::computeDefsForBytecodeOffset):
     59        * bytecode/CodeBlock.cpp:
     60        (JSC::CodeBlock::dumpBytecode):
     61        * bytecode/SpecialPointer.h:
     62        * bytecompiler/BytecodeGenerator.cpp:
     63        (JSC::BytecodeGenerator::emitMoveLinkTimeConstant):
     64        (JSC::BytecodeGenerator::emitCallDefineProperty):
     65        * bytecompiler/BytecodeGenerator.h:
     66        * bytecompiler/NodesCodegen.cpp:
     67        (JSC::PropertyListNode::emitPutConstantProperty):
     68        (JSC::BitwiseNotNode::emitBytecode):
     69        (JSC::ClassExprNode::emitBytecode):
     70        (JSC::ObjectPatternNode::bindValue):
     71        * dfg/DFGAbstractInterpreterInlines.h:
     72        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     73        * dfg/DFGByteCodeParser.cpp:
     74        (JSC::DFG::ByteCodeParser::parseBlock):
     75        * dfg/DFGCapabilities.cpp:
     76        (JSC::DFG::capabilityLevel):
     77        * dfg/DFGClobberize.h:
     78        (JSC::DFG::clobberize):
     79        * dfg/DFGDoesGC.cpp:
     80        (JSC::DFG::doesGC):
     81        * dfg/DFGFixupPhase.cpp:
     82        (JSC::DFG::FixupPhase::fixupNode):
     83        * dfg/DFGNodeType.h:
     84        * dfg/DFGOperations.cpp:
     85        * dfg/DFGOperations.h:
     86        * dfg/DFGPredictionPropagationPhase.cpp:
     87        * dfg/DFGSafeToExecute.h:
     88        (JSC::DFG::safeToExecute):
     89        * dfg/DFGSpeculativeJIT.cpp:
     90        (JSC::DFG::SpeculativeJIT::compileDefineDataProperty):
     91        (JSC::DFG::SpeculativeJIT::compileDefineAccessorProperty):
     92        * dfg/DFGSpeculativeJIT.h:
     93        (JSC::DFG::SpeculativeJIT::callOperation):
     94        * dfg/DFGSpeculativeJIT32_64.cpp:
     95        (JSC::DFG::SpeculativeJIT::compile):
     96        * dfg/DFGSpeculativeJIT64.cpp:
     97        (JSC::DFG::SpeculativeJIT::compile):
     98        * ftl/FTLCapabilities.cpp:
     99        (JSC::FTL::canCompile):
     100        * ftl/FTLLowerDFGToB3.cpp:
     101        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     102        (JSC::FTL::DFG::LowerDFGToB3::compileDefineDataProperty):
     103        (JSC::FTL::DFG::LowerDFGToB3::compileDefineAccessorProperty):
     104        (JSC::FTL::DFG::LowerDFGToB3::compilePutByValWithThis): Deleted.
     105        * jit/CCallHelpers.cpp:
     106        (JSC::CCallHelpers::setupFourStubArgsGPR): Deleted.
     107        * jit/CCallHelpers.h:
     108        (JSC::CCallHelpers::setupFourStubArgsGPR):
     109        (JSC::CCallHelpers::setupFiveStubArgsGPR):
     110        (JSC::CCallHelpers::setupArgumentsWithExecState):
     111        (JSC::CCallHelpers::setupStubArgsGPR):
     112        (JSC::CCallHelpers::prepareForTailCallSlow): Deleted.
     113        * jit/JIT.cpp:
     114        (JSC::JIT::privateCompileMainPass):
     115        * jit/JIT.h:
     116        * jit/JITOperations.h:
     117        * jit/JITPropertyAccess.cpp:
     118        (JSC::JIT::emit_op_define_data_property):
     119        (JSC::JIT::emit_op_define_accessor_property):
     120        * llint/LowLevelInterpreter.asm:
     121        * runtime/CommonSlowPaths.cpp:
     122        (JSC::SLOW_PATH_DECL):
     123        * runtime/CommonSlowPaths.h:
     124        * runtime/DefinePropertyAttributes.h: Added.
     125        (JSC::DefinePropertyAttributes::DefinePropertyAttributes):
     126        (JSC::DefinePropertyAttributes::rawRepresentation):
     127        (JSC::DefinePropertyAttributes::hasValue):
     128        (JSC::DefinePropertyAttributes::setValue):
     129        (JSC::DefinePropertyAttributes::hasGet):
     130        (JSC::DefinePropertyAttributes::setGet):
     131        (JSC::DefinePropertyAttributes::hasSet):
     132        (JSC::DefinePropertyAttributes::setSet):
     133        (JSC::DefinePropertyAttributes::writable):
     134        (JSC::DefinePropertyAttributes::configurable):
     135        (JSC::DefinePropertyAttributes::enumerable):
     136        (JSC::DefinePropertyAttributes::setWritable):
     137        (JSC::DefinePropertyAttributes::setConfigurable):
     138        (JSC::DefinePropertyAttributes::setEnumerable):
     139        (JSC::DefinePropertyAttributes::fillWithTriState):
     140        (JSC::DefinePropertyAttributes::extractTriState):
     141        * runtime/JSGlobalObject.cpp:
     142        (JSC::JSGlobalObject::init):
     143        (JSC::JSGlobalObject::visitChildren):
     144        * runtime/JSGlobalObject.h:
     145        (JSC::JSGlobalObject::throwTypeErrorFunction):
     146        (JSC::JSGlobalObject::definePropertyFunction): Deleted.
     147        * runtime/ObjectConstructor.cpp:
     148        (JSC::ObjectConstructor::addDefineProperty): Deleted.
     149        * runtime/ObjectConstructor.h:
     150        * runtime/PropertyDescriptor.h:
     151        (JSC::toPropertyDescriptor):
     152
    11532016-10-04  Saam Barati  <sbarati@apple.com>
    2154
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r206653 r206778  
    21792179                FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
    21802180                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2181                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; };
    21812182/* End PBXBuildFile section */
    21822183
     
    45194520                FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
    45204521                FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
     4522                169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DefinePropertyAttributes.h; path = DefinePropertyAttributes.h; sourceTree = "<group>"; };
    45214523/* End PBXFileReference section */
    45224524
     
    62706272                                A7DCB77912E3D90500911940 /* WriteBarrier.h */,
    62716273                                C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
     6274                                169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */,
    62726275                        );
    62736276                        path = runtime;
     
    84138416                                A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */,
    84148417                                D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */,
     8418                                473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
    84158419                        );
    84168420                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r206289 r206778  
    8282            { "name" : "op_put_getter_by_val", "length" : 5 },
    8383            { "name" : "op_put_setter_by_val", "length" : 5 },
     84            { "name" : "op_define_data_property", "length" : 5 },
     85            { "name" : "op_define_accessor_property", "length" : 6 },
    8486            { "name" : "op_jmp", "length" : 2 },
    8587            { "name" : "op_jtrue", "length" : 3 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r206525 r206778  
    142142        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
    143143        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
     144        return;
     145    }
     146    case op_define_data_property: {
     147        ASSERT(opcodeLengths[opcodeID] > 4);
     148        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
     149        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     150        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     151        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
     152        return;
     153    }
     154    case op_define_accessor_property: {
     155        ASSERT(opcodeLengths[opcodeID] > 5);
     156        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
     157        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     158        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
     159        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
     160        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
    144161        return;
    145162    }
     
    332349    case op_put_by_val_direct:
    333350    case op_put_by_index:
     351    case op_define_data_property:
     352    case op_define_accessor_property:
    334353    case op_profile_type:
    335354    case op_profile_control_flow:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r206707 r206778  
    12341234            printLocationAndOp(out, exec, location, it, "put_setter_by_val");
    12351235            out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
     1236            break;
     1237        }
     1238        case op_define_data_property: {
     1239            int r0 = (++it)->u.operand;
     1240            int r1 = (++it)->u.operand;
     1241            int r2 = (++it)->u.operand;
     1242            int r3 = (++it)->u.operand;
     1243            printLocationAndOp(out, exec, location, it, "define_data_property");
     1244            out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
     1245            break;
     1246        }
     1247        case op_define_accessor_property: {
     1248            int r0 = (++it)->u.operand;
     1249            int r1 = (++it)->u.operand;
     1250            int r2 = (++it)->u.operand;
     1251            int r3 = (++it)->u.operand;
     1252            int r4 = (++it)->u.operand;
     1253            printLocationAndOp(out, exec, location, it, "define_accessor_property");
     1254            out.printf("%s, %s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), registerName(r4).data());
    12361255            break;
    12371256        }
  • trunk/Source/JavaScriptCore/bytecode/SpecialPointer.h

    r206525 r206778  
    4242
    4343enum class LinkTimeConstant {
    44     DefinePropertyFunction,
     44    ThrowTypeErrorFunction,
    4545};
    4646const unsigned LinkTimeConstantCount = 1;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r206707 r206778  
    3636#include "BytecodeGeneratorification.h"
    3737#include "BytecodeLivenessAnalysis.h"
     38#include "DefinePropertyAttributes.h"
    3839#include "Interpreter.h"
    3940#include "JSFunction.h"
     
    15431544        m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
    15441545    }
     1546
     1547    if (!dst)
     1548        return m_linkTimeConstantRegisters[constantIndex];
    15451549
    15461550    emitOpcode(op_mov);
     
    32753279
    32763280void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
    3277     RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
    3278 {
    3279     RefPtr<RegisterID> descriptorRegister = emitNewObject(newTemporary());
    3280 
    3281     RefPtr<RegisterID> trueRegister = emitLoad(newTemporary(), true);
     3281    RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options)
     3282{
     3283    DefinePropertyAttributes attributes;
    32823284    if (options & PropertyConfigurable)
    3283         emitDirectPutById(descriptorRegister.get(), propertyNames().configurable, trueRegister.get(), PropertyNode::Unknown);
     3285        attributes.setConfigurable(true);
     3286
    32843287    if (options & PropertyWritable)
    3285         emitDirectPutById(descriptorRegister.get(), propertyNames().writable, trueRegister.get(), PropertyNode::Unknown);
    3286     else if (valueRegister) {
    3287         RefPtr<RegisterID> falseRegister = emitLoad(newTemporary(), false);
    3288         emitDirectPutById(descriptorRegister.get(), propertyNames().writable, falseRegister.get(), PropertyNode::Unknown);
    3289     }
     3288        attributes.setWritable(true);
     3289    else if (valueRegister)
     3290        attributes.setWritable(false);
     3291
    32903292    if (options & PropertyEnumerable)
    3291         emitDirectPutById(descriptorRegister.get(), propertyNames().enumerable, trueRegister.get(), PropertyNode::Unknown);
     3293        attributes.setEnumerable(true);
    32923294
    32933295    if (valueRegister)
    3294         emitDirectPutById(descriptorRegister.get(), propertyNames().value, valueRegister, PropertyNode::Unknown);
     3296        attributes.setValue();
    32953297    if (getterRegister)
    3296         emitDirectPutById(descriptorRegister.get(), propertyNames().get, getterRegister, PropertyNode::Unknown);
     3298        attributes.setGet();
    32973299    if (setterRegister)
    3298         emitDirectPutById(descriptorRegister.get(), propertyNames().set, setterRegister, PropertyNode::Unknown);
    3299 
    3300     RefPtr<RegisterID> definePropertyRegister = emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction);
    3301 
    3302     CallArguments callArguments(*this, nullptr, 3);
    3303     emitLoad(callArguments.thisRegister(), jsUndefined());
    3304     emitMove(callArguments.argumentRegister(0), newObj);
    3305     emitMove(callArguments.argumentRegister(1), propertyNameRegister);
    3306     emitMove(callArguments.argumentRegister(2), descriptorRegister.get());
    3307 
    3308     emitCall(newTemporary(), definePropertyRegister.get(), NoExpectedFunction, callArguments, position, position, position, DebuggableCall::No);
     3300        attributes.setSet();
     3301
     3302    ASSERT(!valueRegister || (!getterRegister && !setterRegister));
     3303
     3304    if (attributes.hasGet() || attributes.hasSet()) {
     3305        RefPtr<RegisterID> throwTypeErrorFunction;
     3306        if (!attributes.hasGet() || !attributes.hasSet())
     3307            throwTypeErrorFunction = emitMoveLinkTimeConstant(nullptr, LinkTimeConstant::ThrowTypeErrorFunction);
     3308
     3309        RefPtr<RegisterID> getter;
     3310        if (attributes.hasGet())
     3311            getter = getterRegister;
     3312        else
     3313            getter = throwTypeErrorFunction;
     3314
     3315        RefPtr<RegisterID> setter;
     3316        if (attributes.hasSet())
     3317            setter = setterRegister;
     3318        else
     3319            setter = throwTypeErrorFunction;
     3320
     3321        emitOpcode(op_define_accessor_property);
     3322        instructions().append(newObj->index());
     3323        instructions().append(propertyNameRegister->index());
     3324        instructions().append(getter->index());
     3325        instructions().append(setter->index());
     3326        instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index());
     3327    } else {
     3328        emitOpcode(op_define_data_property);
     3329        instructions().append(newObj->index());
     3330        instructions().append(propertyNameRegister->index());
     3331        instructions().append(valueRegister->index());
     3332        instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index());
     3333    }
    33093334}
    33103335
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r206707 r206778  
    589589        };
    590590        void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
    591             RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
     591            RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options);
    592592
    593593        void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r206653 r206778  
    591591        RefPtr<RegisterID> propertyNameRegister;
    592592        if (node.name())
    593             propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
     593            propertyNameRegister = generator.emitLoad(nullptr, *node.name());
    594594        else
    595595            propertyNameRegister = generator.emitNode(node.m_expression);
    596596
    597597        generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
    598         generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
     598        generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
    599599        return;
    600600    }
     
    606606        }
    607607
    608         RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
     608        RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
    609609        generator.emitDirectPutByVal(newObj, index.get(), value.get());
    610610        return;
     
    16241624RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    16251625{
    1626     RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
     1626    RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
    16271627    RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
    16281628    return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
     
    36103610    }
    36113611
    3612     RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
     3612    RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
    36133613    generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
    3614         BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
    3615 
    3616     RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
    3617     generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
     3614        BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
     3615
     3616    RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
     3617    generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0);
    36183618
    36193619    if (m_staticMethods)
     
    38773877                generator.emitGetById(temp.get(), rhs, target.propertyName);
    38783878            else {
    3879                 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
     3879                RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
    38803880                generator.emitGetByVal(temp.get(), rhs, index.get());
    38813881            }
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r206555 r206778  
    26572657        break;
    26582658    }
     2659
     2660    case DefineDataProperty:
     2661    case DefineAccessorProperty:
     2662        clobberWorld(node->origin.semantic, clobberLimit);
     2663        break;
    26592664       
    26602665    case In: {
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r206267 r206778  
    42374237
    42384238            NEXT_OPCODE(op_put_by_val_with_this);
     4239        }
     4240
     4241        case op_define_data_property: {
     4242            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
     4243            Node* property = get(VirtualRegister(currentInstruction[2].u.operand));
     4244            Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
     4245            Node* attributes = get(VirtualRegister(currentInstruction[4].u.operand));
     4246
     4247            addVarArgChild(base);
     4248            addVarArgChild(property);
     4249            addVarArgChild(value);
     4250            addVarArgChild(attributes);
     4251            addToGraph(Node::VarArg, DefineDataProperty, OpInfo(0), OpInfo(0));
     4252
     4253            NEXT_OPCODE(op_define_data_property);
     4254        }
     4255
     4256        case op_define_accessor_property: {
     4257            Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
     4258            Node* property = get(VirtualRegister(currentInstruction[2].u.operand));
     4259            Node* getter = get(VirtualRegister(currentInstruction[3].u.operand));
     4260            Node* setter = get(VirtualRegister(currentInstruction[4].u.operand));
     4261            Node* attributes = get(VirtualRegister(currentInstruction[5].u.operand));
     4262
     4263            addVarArgChild(base);
     4264            addVarArgChild(property);
     4265            addVarArgChild(getter);
     4266            addVarArgChild(setter);
     4267            addVarArgChild(attributes);
     4268            addToGraph(Node::VarArg, DefineAccessorProperty, OpInfo(0), OpInfo(0));
     4269
     4270            NEXT_OPCODE(op_define_accessor_property);
    42394271        }
    42404272
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r206098 r206778  
    174174    case op_put_getter_by_val:
    175175    case op_put_setter_by_val:
     176    case op_define_data_property:
     177    case op_define_accessor_property:
    176178    case op_del_by_id:
    177179    case op_del_by_val:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r206555 r206778  
    495495    case PutGetterByVal:
    496496    case PutSetterByVal:
     497    case DefineDataProperty:
     498    case DefineAccessorProperty:
    497499    case DeleteById:
    498500    case DeleteByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r206555 r206778  
    112112    case PutGetterByVal:
    113113    case PutSetterByVal:
     114    case DefineDataProperty:
     115    case DefineAccessorProperty:
    114116    case DeleteById:
    115117    case DeleteByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r206767 r206778  
    16551655            fixEdge<UntypedUse>(node->child1());
    16561656#endif // USE(JSVALUE64)
     1657            break;
     1658        }
     1659
     1660        case DefineDataProperty: {
     1661            fixEdge<CellUse>(m_graph.varArgChild(node, 0));
     1662            Edge& propertyEdge = m_graph.varArgChild(node, 1);
     1663            if (propertyEdge->shouldSpeculateSymbol())
     1664                fixEdge<SymbolUse>(propertyEdge);
     1665            else if (propertyEdge->shouldSpeculateStringIdent())
     1666                fixEdge<StringIdentUse>(propertyEdge);
     1667            else if (propertyEdge->shouldSpeculateString())
     1668                fixEdge<StringUse>(propertyEdge);
     1669            else
     1670                fixEdge<UntypedUse>(propertyEdge);
     1671            fixEdge<UntypedUse>(m_graph.varArgChild(node, 2));
     1672            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3));
     1673            break;
     1674        }
     1675
     1676        case DefineAccessorProperty: {
     1677            fixEdge<CellUse>(m_graph.varArgChild(node, 0));
     1678            Edge& propertyEdge = m_graph.varArgChild(node, 1);
     1679            if (propertyEdge->shouldSpeculateSymbol())
     1680                fixEdge<SymbolUse>(propertyEdge);
     1681            else if (propertyEdge->shouldSpeculateStringIdent())
     1682                fixEdge<StringIdentUse>(propertyEdge);
     1683            else if (propertyEdge->shouldSpeculateString())
     1684                fixEdge<StringUse>(propertyEdge);
     1685            else
     1686                fixEdge<UntypedUse>(propertyEdge);
     1687            fixEdge<CellUse>(m_graph.varArgChild(node, 2));
     1688            fixEdge<CellUse>(m_graph.varArgChild(node, 3));
     1689            fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 4));
    16571690            break;
    16581691        }
     
    17271760        case CompareEqPtr:
    17281761            break;
    1729            
    1730             break;
    17311762#else
    17321763        default:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r206555 r206778  
    199199    macro(PutGetterByVal, NodeMustGenerate) \
    200200    macro(PutSetterByVal, NodeMustGenerate) \
     201    macro(DefineDataProperty, NodeMustGenerate | NodeHasVarArgs) \
     202    macro(DefineAccessorProperty, NodeMustGenerate | NodeHasVarArgs) \
    201203    macro(DeleteById, NodeResultBoolean | NodeMustGenerate) \
    202204    macro(DeleteByVal, NodeResultBoolean | NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r206555 r206778  
    3939#include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
    4040#include "DFGWorklist.h"
     41#include "DefinePropertyAttributes.h"
    4142#include "DirectArguments.h"
    4243#include "FTLForOSREntryJITCode.h"
     
    995996}
    996997
     998ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
     999{
     1000    PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
     1001    ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
     1002    if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
     1003        JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
     1004    else
     1005        base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
     1006}
     1007
     1008void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
     1009{
     1010    VM& vm = exec->vm();
     1011    NativeCallFrameTracer tracer(&vm, exec);
     1012    auto scope = DECLARE_THROW_SCOPE(vm);
     1013
     1014    Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
     1015    RETURN_IF_EXCEPTION(scope, void());
     1016    defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
     1017}
     1018
     1019void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
     1020{
     1021    VM& vm = exec->vm();
     1022    NativeCallFrameTracer tracer(&vm, exec);
     1023    auto scope = DECLARE_THROW_SCOPE(vm);
     1024
     1025    Identifier propertyName = property->toIdentifier(exec);
     1026    RETURN_IF_EXCEPTION(scope, void());
     1027    defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
     1028}
     1029
     1030void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
     1031{
     1032    VM& vm = exec->vm();
     1033    NativeCallFrameTracer tracer(&vm, exec);
     1034    defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
     1035}
     1036
     1037void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
     1038{
     1039    VM& vm = exec->vm();
     1040    NativeCallFrameTracer tracer(&vm, exec);
     1041    defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
     1042}
     1043
     1044ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
     1045{
     1046    PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
     1047    ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
     1048    if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
     1049        JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
     1050    else
     1051        base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
     1052}
     1053
     1054void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
     1055{
     1056    VM& vm = exec->vm();
     1057    NativeCallFrameTracer tracer(&vm, exec);
     1058    auto scope = DECLARE_THROW_SCOPE(vm);
     1059
     1060    Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
     1061    RETURN_IF_EXCEPTION(scope, void());
     1062    defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
     1063}
     1064
     1065void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
     1066{
     1067    VM& vm = exec->vm();
     1068    NativeCallFrameTracer tracer(&vm, exec);
     1069    auto scope = DECLARE_THROW_SCOPE(vm);
     1070
     1071    Identifier propertyName = property->toIdentifier(exec);
     1072    RETURN_IF_EXCEPTION(scope, void());
     1073    defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
     1074}
     1075
     1076void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
     1077{
     1078    VM& vm = exec->vm();
     1079    NativeCallFrameTracer tracer(&vm, exec);
     1080    defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
     1081}
     1082
     1083void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
     1084{
     1085    VM& vm = exec->vm();
     1086    NativeCallFrameTracer tracer(&vm, exec);
     1087    defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
     1088}
     1089
    9971090char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
    9981091{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r206525 r206778  
    114114void JIT_OPERATION operationPutByValWithThis(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
    115115void JIT_OPERATION operationPutByValWithThisStrict(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
     116void JIT_OPERATION operationDefineDataProperty(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue, int32_t) WTF_INTERNAL;
     117void JIT_OPERATION operationDefineDataPropertyString(ExecState*, JSObject*, JSString*, EncodedJSValue, int32_t) WTF_INTERNAL;
     118void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, EncodedJSValue, int32_t) WTF_INTERNAL;
     119void JIT_OPERATION operationDefineDataPropertySymbol(ExecState*, JSObject*, Symbol*, EncodedJSValue, int32_t) WTF_INTERNAL;
     120void JIT_OPERATION operationDefineAccessorProperty(ExecState*, JSObject*, EncodedJSValue, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
     121void JIT_OPERATION operationDefineAccessorPropertyString(ExecState*, JSObject*, JSString*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
     122void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
     123void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
    116124EncodedJSValue JIT_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
    117125EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r206555 r206778  
    10421042        case PutGetterByVal:
    10431043        case PutSetterByVal:
     1044        case DefineDataProperty:
     1045        case DefineAccessorProperty:
    10441046        case DFG::Jump:
    10451047        case Branch:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r206555 r206778  
    214214    case PutGetterByVal:
    215215    case PutSetterByVal:
     216    case DefineDataProperty:
     217    case DefineAccessorProperty:
    216218    case CheckStructure:
    217219    case GetExecutable:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r206555 r206778  
    86458645}
    86468646
     8647void SpeculativeJIT::compileDefineDataProperty(Node* node)
     8648{
     8649#if USE(JSVALUE64)
     8650    static_assert(GPRInfo::numberOfRegisters >= 5, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
     8651#else
     8652    static_assert(GPRInfo::numberOfRegisters >= 6, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
     8653#endif
     8654
     8655    SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 0));
     8656    GPRReg baseGPR = base.gpr();
     8657
     8658    JSValueOperand value(this, m_jit.graph().varArgChild(node, 2));
     8659    JSValueRegs valueRegs = value.jsValueRegs();
     8660
     8661    SpeculateInt32Operand attributes(this, m_jit.graph().varArgChild(node, 3));
     8662    GPRReg attributesGPR = attributes.gpr();
     8663
     8664    Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
     8665    switch (propertyEdge.useKind()) {
     8666    case StringUse: {
     8667        SpeculateCellOperand property(this, propertyEdge);
     8668        GPRReg propertyGPR = property.gpr();
     8669        speculateString(propertyEdge, propertyGPR);
     8670
     8671        useChildren(node);
     8672
     8673        flushRegisters();
     8674        callOperation(operationDefineDataPropertyString, NoResult, baseGPR, propertyGPR, valueRegs, attributesGPR);
     8675        m_jit.exceptionCheck();
     8676        break;
     8677    }
     8678    case StringIdentUse: {
     8679        SpeculateCellOperand property(this, propertyEdge);
     8680        GPRTemporary ident(this);
     8681
     8682        GPRReg propertyGPR = property.gpr();
     8683        GPRReg identGPR = ident.gpr();
     8684
     8685        speculateString(propertyEdge, propertyGPR);
     8686        speculateStringIdentAndLoadStorage(propertyEdge, propertyGPR, identGPR);
     8687
     8688        useChildren(node);
     8689
     8690        flushRegisters();
     8691        callOperation(operationDefineDataPropertyStringIdent, NoResult, baseGPR, identGPR, valueRegs, attributesGPR);
     8692        m_jit.exceptionCheck();
     8693        break;
     8694    }
     8695    case SymbolUse: {
     8696        SpeculateCellOperand property(this, propertyEdge);
     8697        GPRReg propertyGPR = property.gpr();
     8698        speculateSymbol(propertyEdge, propertyGPR);
     8699
     8700        useChildren(node);
     8701
     8702        flushRegisters();
     8703        callOperation(operationDefineDataPropertySymbol, NoResult, baseGPR, propertyGPR, valueRegs, attributesGPR);
     8704        m_jit.exceptionCheck();
     8705        break;
     8706    }
     8707    case UntypedUse: {
     8708        JSValueOperand property(this, propertyEdge);
     8709        JSValueRegs propertyRegs = property.jsValueRegs();
     8710
     8711        useChildren(node);
     8712
     8713        flushRegisters();
     8714        callOperation(operationDefineDataProperty, NoResult, baseGPR, propertyRegs, valueRegs, attributesGPR);
     8715        m_jit.exceptionCheck();
     8716        break;
     8717    }
     8718    default:
     8719        RELEASE_ASSERT_NOT_REACHED();
     8720    }
     8721
     8722    noResult(node, UseChildrenCalledExplicitly);
     8723}
     8724
     8725void SpeculativeJIT::compileDefineAccessorProperty(Node* node)
     8726{
     8727#if USE(JSVALUE64)
     8728    static_assert(GPRInfo::numberOfRegisters >= 5, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
     8729#else
     8730    static_assert(GPRInfo::numberOfRegisters >= 6, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
     8731#endif
     8732
     8733    SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 0));
     8734    GPRReg baseGPR = base.gpr();
     8735
     8736    SpeculateCellOperand getter(this, m_jit.graph().varArgChild(node, 2));
     8737    GPRReg getterGPR = getter.gpr();
     8738
     8739    SpeculateCellOperand setter(this, m_jit.graph().varArgChild(node, 3));
     8740    GPRReg setterGPR = setter.gpr();
     8741
     8742    SpeculateInt32Operand attributes(this, m_jit.graph().varArgChild(node, 4));
     8743    GPRReg attributesGPR = attributes.gpr();
     8744
     8745    Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
     8746    switch (propertyEdge.useKind()) {
     8747    case StringUse: {
     8748        SpeculateCellOperand property(this, propertyEdge);
     8749        GPRReg propertyGPR = property.gpr();
     8750        speculateString(propertyEdge, propertyGPR);
     8751
     8752        useChildren(node);
     8753
     8754        flushRegisters();
     8755        callOperation(operationDefineAccessorPropertyString, NoResult, baseGPR, propertyGPR, getterGPR, setterGPR, attributesGPR);
     8756        m_jit.exceptionCheck();
     8757        break;
     8758    }
     8759    case StringIdentUse: {
     8760        SpeculateCellOperand property(this, propertyEdge);
     8761        GPRTemporary ident(this);
     8762
     8763        GPRReg propertyGPR = property.gpr();
     8764        GPRReg identGPR = ident.gpr();
     8765
     8766        speculateString(propertyEdge, propertyGPR);
     8767        speculateStringIdentAndLoadStorage(propertyEdge, propertyGPR, identGPR);
     8768
     8769        useChildren(node);
     8770
     8771        flushRegisters();
     8772        callOperation(operationDefineAccessorPropertyStringIdent, NoResult, baseGPR, identGPR, getterGPR, setterGPR, attributesGPR);
     8773        m_jit.exceptionCheck();
     8774        break;
     8775    }
     8776    case SymbolUse: {
     8777        SpeculateCellOperand property(this, propertyEdge);
     8778        GPRReg propertyGPR = property.gpr();
     8779        speculateSymbol(propertyEdge, propertyGPR);
     8780
     8781        useChildren(node);
     8782
     8783        flushRegisters();
     8784        callOperation(operationDefineAccessorPropertySymbol, NoResult, baseGPR, propertyGPR, getterGPR, setterGPR, attributesGPR);
     8785        m_jit.exceptionCheck();
     8786        break;
     8787    }
     8788    case UntypedUse: {
     8789        JSValueOperand property(this, propertyEdge);
     8790        JSValueRegs propertyRegs = property.jsValueRegs();
     8791
     8792        useChildren(node);
     8793
     8794        flushRegisters();
     8795        callOperation(operationDefineAccessorProperty, NoResult, baseGPR, propertyRegs, getterGPR, setterGPR, attributesGPR);
     8796        m_jit.exceptionCheck();
     8797        break;
     8798    }
     8799    default:
     8800        RELEASE_ASSERT_NOT_REACHED();
     8801    }
     8802
     8803    noResult(node, UseChildrenCalledExplicitly);
     8804}
     8805
    86478806} } // namespace JSC::DFG
    86488807
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r206555 r206778  
    13361336        return appendCall(operation);
    13371337    }
     1338    JITCompiler::Call callOperation(V_JITOperation_EOJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
     1339    {
     1340        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3.payloadGPR(), arg4);
     1341        return appendCall(operation);
     1342    }
     1343    JITCompiler::Call callOperation(V_JITOperation_EOJssJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1344    {
     1345        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
     1346        return appendCall(operation);
     1347    }
     1348    JITCompiler::Call callOperation(V_JITOperation_EOIJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1349    {
     1350        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
     1351        return appendCall(operation);
     1352    }
     1353    JITCompiler::Call callOperation(V_JITOperation_EOSymJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1354    {
     1355        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
     1356        return appendCall(operation);
     1357    }
     1358    JITCompiler::Call callOperation(V_JITOperation_EOJOOZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1359    {
     1360        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3, arg4, arg5);
     1361        return appendCall(operation);
     1362    }
     1363    JITCompiler::Call callOperation(V_JITOperation_EOJssOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1364    {
     1365        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1366        return appendCall(operation);
     1367    }
     1368    JITCompiler::Call callOperation(V_JITOperation_EOIOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1369    {
     1370        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1371        return appendCall(operation);
     1372    }
     1373    JITCompiler::Call callOperation(V_JITOperation_EOSymOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1374    {
     1375        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1376        return appendCall(operation);
     1377    }
    13381378    JITCompiler::Call callOperation(V_JITOperation_EOJIUi operation, GPRReg arg1, GPRReg arg2, UniquedStringImpl* impl, unsigned value)
    13391379    {
     
    17801820        return appendCall(operation);
    17811821    }
    1782 
     1822    JITCompiler::Call callOperation(V_JITOperation_EOJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
     1823    {
     1824        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3.payloadGPR(), arg3.tagGPR(), arg4);
     1825        return appendCall(operation);
     1826    }
     1827    JITCompiler::Call callOperation(V_JITOperation_EOJssJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1828    {
     1829        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
     1830        return appendCall(operation);
     1831    }
     1832    JITCompiler::Call callOperation(V_JITOperation_EOIJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1833    {
     1834        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
     1835        return appendCall(operation);
     1836    }
     1837    JITCompiler::Call callOperation(V_JITOperation_EOSymJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
     1838    {
     1839        m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
     1840        return appendCall(operation);
     1841    }
     1842    JITCompiler::Call callOperation(V_JITOperation_EOJOOZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1843    {
     1844        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4, arg5);
     1845        return appendCall(operation);
     1846    }
     1847    JITCompiler::Call callOperation(V_JITOperation_EOJssOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1848    {
     1849        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1850        return appendCall(operation);
     1851    }
     1852    JITCompiler::Call callOperation(V_JITOperation_EOIOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1853    {
     1854        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1855        return appendCall(operation);
     1856    }
     1857    JITCompiler::Call callOperation(V_JITOperation_EOSymOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     1858    {
     1859        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
     1860        return appendCall(operation);
     1861    }
    17831862    JITCompiler::Call callOperation(V_JITOperation_EOJIUi operation, GPRReg arg1, JSValueRegs arg2, UniquedStringImpl* impl, unsigned value)
    17841863    {
     
    25712650    void compilePutDynamicVar(Node*);
    25722651    void compileCompareEqPtr(Node*);
     2652    void compileDefineDataProperty(Node*);
     2653    void compileDefineAccessorProperty(Node*);
    25732654
    25742655    void moveTrueTo(GPRReg);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r206555 r206778  
    44804480    }
    44814481
     4482    case DefineDataProperty: {
     4483        compileDefineDataProperty(node);
     4484        break;
     4485    }
     4486
     4487    case DefineAccessorProperty: {
     4488        compileDefineAccessorProperty(node);
     4489        break;
     4490    }
     4491
    44824492    case GetGlobalLexicalVariable:
    44834493    case GetGlobalVar: {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r206763 r206778  
    44384438    }
    44394439
     4440    case DefineDataProperty: {
     4441        compileDefineDataProperty(node);
     4442        break;
     4443    }
     4444
     4445    case DefineAccessorProperty: {
     4446        compileDefineAccessorProperty(node);
     4447        break;
     4448    }
     4449
    44404450    case GetGlobalLexicalVariable:
    44414451    case GetGlobalVar: {
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r206555 r206778  
    264264    case CompareGreaterEq:
    265265    case CompareStrictEq:
     266    case DefineDataProperty:
     267    case DefineAccessorProperty:
    266268        // These are OK.
    267269        break;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r206763 r206778  
    692692            compilePutByValWithThis();
    693693            break;
     694        case DefineDataProperty:
     695            compileDefineDataProperty();
     696            break;
     697        case DefineAccessorProperty:
     698            compileDefineAccessorProperty();
     699            break;
    694700        case ArrayPush:
    695701            compileArrayPush();
     
    27632769        vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis),
    27642770            m_callFrame, base, thisValue, property, value);
     2771    }
     2772
     2773    void compileDefineDataProperty()
     2774    {
     2775        LValue base = lowCell(m_graph.varArgChild(m_node, 0));
     2776        LValue value  = lowJSValue(m_graph.varArgChild(m_node, 2));
     2777        LValue attributes = lowInt32(m_graph.varArgChild(m_node, 3));
     2778        Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
     2779        switch (propertyEdge.useKind()) {
     2780        case StringUse: {
     2781            LValue property = lowString(propertyEdge);
     2782            vmCall(Void, m_out.operation(operationDefineDataPropertyString), m_callFrame, base, property, value, attributes);
     2783            break;
     2784        }
     2785        case StringIdentUse: {
     2786            LValue property = lowStringIdent(propertyEdge);
     2787            vmCall(Void, m_out.operation(operationDefineDataPropertyStringIdent), m_callFrame, base, property, value, attributes);
     2788            break;
     2789        }
     2790        case SymbolUse: {
     2791            LValue property = lowSymbol(propertyEdge);
     2792            vmCall(Void, m_out.operation(operationDefineDataPropertySymbol), m_callFrame, base, property, value, attributes);
     2793            break;
     2794        }
     2795        case UntypedUse: {
     2796            LValue property = lowJSValue(propertyEdge);
     2797            vmCall(Void, m_out.operation(operationDefineDataProperty), m_callFrame, base, property, value, attributes);
     2798            break;
     2799        }
     2800        default:
     2801            RELEASE_ASSERT_NOT_REACHED();
     2802        }
     2803    }
     2804
     2805    void compileDefineAccessorProperty()
     2806    {
     2807        LValue base = lowCell(m_graph.varArgChild(m_node, 0));
     2808        LValue getter = lowCell(m_graph.varArgChild(m_node, 2));
     2809        LValue setter = lowCell(m_graph.varArgChild(m_node, 3));
     2810        LValue attributes = lowInt32(m_graph.varArgChild(m_node, 4));
     2811        Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
     2812        switch (propertyEdge.useKind()) {
     2813        case StringUse: {
     2814            LValue property = lowString(propertyEdge);
     2815            vmCall(Void, m_out.operation(operationDefineAccessorPropertyString), m_callFrame, base, property, getter, setter, attributes);
     2816            break;
     2817        }
     2818        case StringIdentUse: {
     2819            LValue property = lowStringIdent(propertyEdge);
     2820            vmCall(Void, m_out.operation(operationDefineAccessorPropertyStringIdent), m_callFrame, base, property, getter, setter, attributes);
     2821            break;
     2822        }
     2823        case SymbolUse: {
     2824            LValue property = lowSymbol(propertyEdge);
     2825            vmCall(Void, m_out.operation(operationDefineAccessorPropertySymbol), m_callFrame, base, property, getter, setter, attributes);
     2826            break;
     2827        }
     2828        case UntypedUse: {
     2829            LValue property = lowJSValue(propertyEdge);
     2830            vmCall(Void, m_out.operation(operationDefineAccessorProperty), m_callFrame, base, property, getter, setter, attributes);
     2831            break;
     2832        }
     2833        default:
     2834            RELEASE_ASSERT_NOT_REACHED();
     2835        }
    27652836    }
    27662837   
  • trunk/Source/JavaScriptCore/jit/CCallHelpers.cpp

    r203006 r206778  
    6969}
    7070
    71 #if NUMBER_OF_ARGUMENT_REGISTERS >= 4
    72 void CCallHelpers::setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD)
    73 {
    74     if (!ASSERT_DISABLED) {
    75         RegisterSet destinations(destA, destB, destC, destD);
    76         ASSERT_WITH_MESSAGE(destinations.numberOfSetGPRs() == 4, "Destinations should not be aliased.");
    77     }
    78 
    79     typedef std::pair<GPRReg, GPRReg> RegPair;
    80     Vector<RegPair, 4> pairs;
    81 
    82     if (srcA != destA)
    83         pairs.append(std::make_pair(srcA, destA));
    84     if (srcB != destB)
    85         pairs.append(std::make_pair(srcB, destB));
    86     if (srcC != destC)
    87         pairs.append(std::make_pair(srcC, destC));
    88     if (srcD != destD)
    89         pairs.append(std::make_pair(srcD, destD));
    90 
    91 
    92 #if !ASSERT_DISABLED
    93     auto numUniqueSources = [&] () -> unsigned {
    94         RegisterSet set;
    95         for (auto& pair : pairs) {
    96             GPRReg source = pair.first;
    97             set.set(source);
    98         }
    99         return set.numberOfSetGPRs();
    100     };
    101 
    102     auto numUniqueDests = [&] () -> unsigned {
    103         RegisterSet set;
    104         for (auto& pair : pairs) {
    105             GPRReg dest = pair.second;
    106             set.set(dest);
    107         }
    108         return set.numberOfSetGPRs();
    109     };
    110 #endif
    111 
    112     while (pairs.size()) {
    113         RegisterSet freeDestinations;
    114         for (auto& pair : pairs) {
    115             GPRReg dest = pair.second;
    116             freeDestinations.set(dest);
    117         }
    118         for (auto& pair : pairs) {
    119             GPRReg source = pair.first;
    120             freeDestinations.clear(source);
    121         }
    122 
    123         if (freeDestinations.numberOfSetGPRs()) {
    124             bool madeMove = false;
    125             for (unsigned i = 0; i < pairs.size(); i++) {
    126                 auto& pair = pairs[i];
    127                 GPRReg source = pair.first;
    128                 GPRReg dest = pair.second;
    129                 if (freeDestinations.get(dest)) {
    130                     move(source, dest);
    131                     pairs.remove(i);
    132                     madeMove = true;
    133                     break;
    134                 }
    135             }
    136             ASSERT_UNUSED(madeMove, madeMove);
    137             continue;
    138         }
    139 
    140         ASSERT(numUniqueDests() == numUniqueSources());
    141         ASSERT(numUniqueDests() == pairs.size());
    142         // The set of source and destination registers are equivalent sets. This means we don't have
    143         // any free destination registers that won't also clobber a source. We get around this by
    144         // exchanging registers.
    145 
    146         GPRReg source = pairs[0].first;
    147         GPRReg dest = pairs[0].second;
    148         swap(source, dest);
    149         pairs.remove(0);
    150 
    151         GPRReg newSource = source;
    152         for (auto& pair : pairs) {
    153             GPRReg source = pair.first;
    154             if (source == dest) {
    155                 pair.first = newSource;
    156                 break;
    157             }
    158         }
    159 
    160         // We may have introduced pairs that have the same source and destination. Remove those now.
    161         for (unsigned i = 0; i < pairs.size(); i++) {
    162             auto& pair = pairs[i];
    163             if (pair.first == pair.second) {
    164                 pairs.remove(i);
    165                 i--;
    166             }
    167         }
    168     }
    169 }
    170 #endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
    171 
    17271} // namespace JSC
    17372
  • trunk/Source/JavaScriptCore/jit/CCallHelpers.h

    r206525 r206778  
    987987    }
    988988
    989     void setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD);
     989    void setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD)
     990    {
     991        setupStubArgsGPR<4>({ { destA, destB, destC, destD } }, { { srcA, srcB, srcC, srcD } });
     992    }
     993    void setupFiveStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg destE, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD, GPRReg srcE)
     994    {
     995        setupStubArgsGPR<5>({ { destA, destB, destC, destD, destE } }, { { srcA, srcB, srcC, srcD, srcE } });
     996    }
    990997
    991998#if CPU(X86_64) || CPU(ARM64)
     
    21812188        move(arg2, GPRInfo::argumentGPR2);
    21822189        move(arg3, GPRInfo::argumentGPR3);
     2190        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     2191    }
     2192
     2193    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
     2194    {
     2195        setupFiveStubArgsGPR(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, GPRInfo::argumentGPR4, GPRInfo::argumentGPR5, arg1, arg2, arg3, arg4, arg5);
    21832196        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    21842197    }
     
    24722485        move(newFramePointer, stackPointerRegister);
    24732486    }
     2487
     2488#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
     2489    template<unsigned NumberOfRegisters>
     2490    void setupStubArgsGPR(std::array<GPRReg, NumberOfRegisters> destinations, std::array<GPRReg, NumberOfRegisters> sources)
     2491    {
     2492        if (!ASSERT_DISABLED) {
     2493            RegisterSet set;
     2494            for (GPRReg dest : destinations)
     2495                set.set(dest);
     2496            ASSERT_WITH_MESSAGE(set.numberOfSetGPRs() == NumberOfRegisters, "Destinations should not be aliased.");
     2497        }
     2498
     2499        typedef std::pair<GPRReg, GPRReg> RegPair;
     2500        Vector<RegPair, NumberOfRegisters> pairs;
     2501
     2502        for (unsigned i = 0; i < NumberOfRegisters; ++i) {
     2503            if (sources[i] != destinations[i])
     2504                pairs.append(std::make_pair(sources[i], destinations[i]));
     2505        }
     2506
     2507#if !ASSERT_DISABLED
     2508        auto numUniqueSources = [&] () -> unsigned {
     2509            RegisterSet set;
     2510            for (auto& pair : pairs) {
     2511                GPRReg source = pair.first;
     2512                set.set(source);
     2513            }
     2514            return set.numberOfSetGPRs();
     2515        };
     2516
     2517        auto numUniqueDests = [&] () -> unsigned {
     2518            RegisterSet set;
     2519            for (auto& pair : pairs) {
     2520                GPRReg dest = pair.second;
     2521                set.set(dest);
     2522            }
     2523            return set.numberOfSetGPRs();
     2524        };
     2525#endif
     2526
     2527        while (pairs.size()) {
     2528            RegisterSet freeDestinations;
     2529            for (auto& pair : pairs) {
     2530                GPRReg dest = pair.second;
     2531                freeDestinations.set(dest);
     2532            }
     2533            for (auto& pair : pairs) {
     2534                GPRReg source = pair.first;
     2535                freeDestinations.clear(source);
     2536            }
     2537
     2538            if (freeDestinations.numberOfSetGPRs()) {
     2539                bool madeMove = false;
     2540                for (unsigned i = 0; i < pairs.size(); i++) {
     2541                    auto& pair = pairs[i];
     2542                    GPRReg source = pair.first;
     2543                    GPRReg dest = pair.second;
     2544                    if (freeDestinations.get(dest)) {
     2545                        move(source, dest);
     2546                        pairs.remove(i);
     2547                        madeMove = true;
     2548                        break;
     2549                    }
     2550                }
     2551                ASSERT_UNUSED(madeMove, madeMove);
     2552                continue;
     2553            }
     2554
     2555            ASSERT(numUniqueDests() == numUniqueSources());
     2556            ASSERT(numUniqueDests() == pairs.size());
     2557            // The set of source and destination registers are equivalent sets. This means we don't have
     2558            // any free destination registers that won't also clobber a source. We get around this by
     2559            // exchanging registers.
     2560
     2561            GPRReg source = pairs[0].first;
     2562            GPRReg dest = pairs[0].second;
     2563            swap(source, dest);
     2564            pairs.remove(0);
     2565
     2566            GPRReg newSource = source;
     2567            for (auto& pair : pairs) {
     2568                GPRReg source = pair.first;
     2569                if (source == dest) {
     2570                    pair.first = newSource;
     2571                    break;
     2572                }
     2573            }
     2574
     2575            // We may have introduced pairs that have the same source and destination. Remove those now.
     2576            for (unsigned i = 0; i < pairs.size(); i++) {
     2577                auto& pair = pairs[i];
     2578                if (pair.first == pair.second) {
     2579                    pairs.remove(i);
     2580                    i--;
     2581                }
     2582            }
     2583        }
     2584    }
     2585#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
    24742586   
    24752587    // These operations clobber all volatile registers. They assume that there is room on the top of
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r206267 r206778  
    323323        DEFINE_OP(op_put_getter_by_val)
    324324        DEFINE_OP(op_put_setter_by_val)
     325        DEFINE_OP(op_define_data_property)
     326        DEFINE_OP(op_define_accessor_property)
    325327
    326328        DEFINE_OP(op_ret)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r206525 r206778  
    567567        void emit_op_put_getter_by_val(Instruction*);
    568568        void emit_op_put_setter_by_val(Instruction*);
     569        void emit_op_define_data_property(Instruction*);
     570        void emit_op_define_accessor_property(Instruction*);
    569571        void emit_op_ret(Instruction*);
    570572        void emit_op_rshift(Instruction*);
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r206555 r206778  
    5959class Structure;
    6060class StructureStubInfo;
     61class Symbol;
    6162class SymbolTable;
    6263class WatchpointSet;
     
    111112    St: Structure*
    112113    Symtab: SymbolTable*
     114    Sym: Symbol*
    113115    T: StringImpl*
    114116    V: void
     
    269271typedef void (JIT_OPERATION *V_JITOperation_EJJJI)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, UniquedStringImpl*);
    270272typedef void (JIT_OPERATION *V_JITOperation_EJJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue);
     273typedef void (JIT_OPERATION *V_JITOperation_EOJJZ)(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue, int32_t);
     274typedef void (JIT_OPERATION *V_JITOperation_EOJssJZ)(ExecState*, JSObject*, JSString*, EncodedJSValue, int32_t);
     275typedef void (JIT_OPERATION *V_JITOperation_EOIJZ)(ExecState*, JSObject*, UniquedStringImpl*, EncodedJSValue, int32_t);
     276typedef void (JIT_OPERATION *V_JITOperation_EOSymJZ)(ExecState*, JSObject*, Symbol*, EncodedJSValue, int32_t);
     277typedef void (JIT_OPERATION *V_JITOperation_EOJOOZ)(ExecState*, JSObject*, EncodedJSValue, JSObject*, JSObject*, int32_t);
     278typedef void (JIT_OPERATION *V_JITOperation_EOJssOOZ)(ExecState*, JSObject*, JSString*, JSObject*, JSObject*, int32_t);
     279typedef void (JIT_OPERATION *V_JITOperation_EOIOOZ)(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t);
     280typedef void (JIT_OPERATION *V_JITOperation_EOSymOOZ)(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t);
    271281typedef void (JIT_OPERATION *V_JITOperation_EWs)(ExecState*, WatchpointSet*);
    272282typedef void (JIT_OPERATION *V_JITOperation_EZ)(ExecState*, int32_t);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r206628 r206778  
    17711771}
    17721772
     1773void JIT::emit_op_define_data_property(Instruction* currentInstruction)
     1774{
     1775    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_define_data_property);
     1776    slowPathCall.call();
     1777}
     1778
     1779void JIT::emit_op_define_accessor_property(Instruction* currentInstruction)
     1780{
     1781    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_define_accessor_property);
     1782    slowPathCall.call();
     1783}
     1784
    17731785} // namespace JSC
    17741786
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r206555 r206778  
    14591459
    14601460
     1461_llint_op_define_data_property:
     1462    traceExecution()
     1463    callOpcodeSlowPath(_slow_path_define_data_property)
     1464    dispatch(5)
     1465
     1466
     1467_llint_op_define_accessor_property:
     1468    traceExecution()
     1469    callOpcodeSlowPath(_slow_path_define_accessor_property)
     1470    dispatch(6)
     1471
     1472
    14611473_llint_op_jtrue:
    14621474    traceExecution()
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r206289 r206778  
    3434#include "CodeProfiling.h"
    3535#include "CommonSlowPathsExceptions.h"
     36#include "DefinePropertyAttributes.h"
    3637#include "DirectArguments.h"
    3738#include "Error.h"
     
    931932}
    932933
     934SLOW_PATH_DECL(slow_path_define_data_property)
     935{
     936    BEGIN();
     937    JSObject* base = asObject(OP_C(1).jsValue());
     938    JSValue property = OP_C(2).jsValue();
     939    JSValue value = OP_C(3).jsValue();
     940    JSValue attributes = OP_C(4).jsValue();
     941    ASSERT(attributes.isInt32());
     942
     943    auto propertyName = property.toPropertyKey(exec);
     944    CHECK_EXCEPTION();
     945    PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
     946    ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
     947    base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
     948    END();
     949}
     950
     951SLOW_PATH_DECL(slow_path_define_accessor_property)
     952{
     953    BEGIN();
     954    JSObject* base = asObject(OP_C(1).jsValue());
     955    JSValue property = OP_C(2).jsValue();
     956    JSValue getter = OP_C(3).jsValue();
     957    JSValue setter = OP_C(4).jsValue();
     958    JSValue attributes = OP_C(5).jsValue();
     959    ASSERT(attributes.isInt32());
     960
     961    auto propertyName = property.toPropertyKey(exec);
     962    CHECK_EXCEPTION();
     963    PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
     964    ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
     965    base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
     966    END();
     967}
     968
    933969} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r206525 r206778  
    257257SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id_with_this);
    258258SLOW_PATH_HIDDEN_DECL(slow_path_put_by_val_with_this);
     259SLOW_PATH_HIDDEN_DECL(slow_path_define_data_property);
     260SLOW_PATH_HIDDEN_DECL(slow_path_define_accessor_property);
    259261
    260262} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r206711 r206778  
    405405    m_throwTypeErrorGetterSetter.initLater(
    406406        [] (const Initializer<GetterSetter>& init) {
    407             JSFunction* thrower = JSFunction::create(init.vm, init.owner, 0, String(), globalFuncThrowTypeError);
     407            JSFunction* thrower = init.owner->throwTypeErrorFunction();
    408408            GetterSetter* getterSetter = GetterSetter::create(init.vm, init.owner);
    409409            getterSetter->setGetter(init.vm, init.owner, thrower);
     
    582582    m_objectConstructor.set(vm, this, objectConstructor);
    583583
    584     JSFunction* definePropertyFunction = m_objectConstructor->addDefineProperty(exec, this);
    585     m_definePropertyFunction.set(vm, this, definePropertyFunction);
     584    JSFunction* throwTypeErrorFunction = JSFunction::create(vm, this, 0, String(), globalFuncThrowTypeError);
     585    m_throwTypeErrorFunction.set(vm, this, throwTypeErrorFunction);
    586586
    587587    JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
     
    804804    m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
    805805
    806     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::DefinePropertyFunction)] = m_definePropertyFunction.get();
     806    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::ThrowTypeErrorFunction)] = m_throwTypeErrorFunction.get();
    807807
    808808    if (UNLIKELY(Options::useDollarVM())) {
     
    10671067    visitor.append(&thisObject->m_callFunction);
    10681068    visitor.append(&thisObject->m_applyFunction);
    1069     visitor.append(&thisObject->m_definePropertyFunction);
     1069    visitor.append(&thisObject->m_throwTypeErrorFunction);
    10701070    thisObject->m_arrayProtoToStringFunction.visit(visitor);
    10711071    thisObject->m_arrayProtoValuesFunction.visit(visitor);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r206525 r206778  
    234234    WriteBarrier<JSFunction> m_callFunction;
    235235    WriteBarrier<JSFunction> m_applyFunction;
    236     WriteBarrier<JSFunction> m_definePropertyFunction;
     236    WriteBarrier<JSFunction> m_throwTypeErrorFunction;
    237237    LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoToStringFunction;
    238238    LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoValuesFunction;
     
    479479    JSFunction* callFunction() const { return m_callFunction.get(); }
    480480    JSFunction* applyFunction() const { return m_applyFunction.get(); }
    481     JSFunction* definePropertyFunction() const { return m_definePropertyFunction.get(); }
     481    JSFunction* throwTypeErrorFunction() const { return m_throwTypeErrorFunction.get(); }
    482482    JSFunction* arrayProtoToStringFunction() const { return m_arrayProtoToStringFunction.get(this); }
    483483    JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(this); }
  • trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp

    r206386 r206778  
    108108}
    109109
    110 JSFunction* ObjectConstructor::addDefineProperty(ExecState* exec, JSGlobalObject* globalObject)
    111 {
    112     VM& vm = exec->vm();
    113     JSFunction* definePropertyFunction = JSFunction::create(vm, globalObject, 3, vm.propertyNames->defineProperty.string(), objectConstructorDefineProperty);
    114     putDirectWithoutTransition(vm, vm.propertyNames->defineProperty, definePropertyFunction, DontEnum);
    115     return definePropertyFunction;
    116 }
    117 
    118110// ES 19.1.1.1 Object([value])
    119111static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSValue newTarget)
  • trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h

    r206525 r206778  
    5353        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
    5454    }
    55 
    56     JSFunction* addDefineProperty(ExecState*, JSGlobalObject*);
    5755
    5856protected:
  • trunk/Source/JavaScriptCore/runtime/PropertyDescriptor.h

    r206525 r206778  
    2626#pragma once
    2727
     28#include "DefinePropertyAttributes.h"
    2829#include "JSCJSValue.h"
    2930
     
    9394};
    9495
    95 } // namespace JSC
     96inline PropertyDescriptor toPropertyDescriptor(JSValue value, JSValue getter, JSValue setter, DefinePropertyAttributes attributes)
     97{
     98    // We assume that validation is already done.
     99    PropertyDescriptor desc;
     100
     101    if (Optional<bool> enumerable = attributes.enumerable())
     102        desc.setEnumerable(enumerable.value());
     103
     104    if (Optional<bool> configurable = attributes.configurable())
     105        desc.setConfigurable(configurable.value());
     106
     107    if (attributes.hasValue())
     108        desc.setValue(value);
     109
     110    if (Optional<bool> writable = attributes.writable())
     111        desc.setWritable(writable.value());
     112
     113    if (attributes.hasGet())
     114        desc.setGetter(getter);
     115
     116    if (attributes.hasSet())
     117        desc.setSetter(setter);
     118
     119    return desc;
     120}
     121
     122}
Note: See TracChangeset for help on using the changeset viewer.