Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (206777 => 206778)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1,3 +1,155 @@
+2016-09-27 Yusuke Suzuki <utatane....@gmail.com>
+
+ [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
+
+ * _javascript_Core.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):
+
2016-10-04 Saam Barati <sbar...@apple.com>
Follow up fix to GetMapBucket and MapHash speculating on child node types.
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (206777 => 206778)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-04 19:31:24 UTC (rev 206778)
@@ -2178,6 +2178,7 @@
FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */; settings = {ATTRIBUTES = (Private, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -4518,6 +4519,7 @@
FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringInlines.h; sourceTree = "<group>"; };
+ 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DefinePropertyAttributes.h; path = DefinePropertyAttributes.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -6269,6 +6271,7 @@
709FB8661AE335C60039D069 /* WeakSetPrototype.h */,
A7DCB77912E3D90500911940 /* WriteBarrier.h */,
C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
+ 169948EDE68D4054B01EF797 /* DefinePropertyAttributes.h */,
);
path = runtime;
sourceTree = "<group>";
@@ -8412,6 +8415,7 @@
86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */,
D9722752DC54459B9125B539 /* JSModuleLoader.h in Headers */,
+ 473DA4A4764C45FE871B0485 /* DefinePropertyAttributes.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json 2016-10-04 19:31:24 UTC (rev 206778)
@@ -81,6 +81,8 @@
{ "name" : "op_put_getter_setter_by_id", "length" : 6 },
{ "name" : "op_put_getter_by_val", "length" : 5 },
{ "name" : "op_put_setter_by_val", "length" : 5 },
+ { "name" : "op_define_data_property", "length" : 5 },
+ { "name" : "op_define_accessor_property", "length" : 6 },
{ "name" : "op_jmp", "length" : 2 },
{ "name" : "op_jtrue", "length" : 3 },
{ "name" : "op_jfalse", "length" : 3 },
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -143,6 +143,23 @@
functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
return;
}
+ case op_define_data_property: {
+ ASSERT(opcodeLengths[opcodeID] > 4);
+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
+ return;
+ }
+ case op_define_accessor_property: {
+ ASSERT(opcodeLengths[opcodeID] > 5);
+ functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
+ functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
+ return;
+ }
case op_get_property_enumerator:
case op_get_enumerable_length:
case op_new_func_exp:
@@ -331,6 +348,8 @@
case op_put_by_val:
case op_put_by_val_direct:
case op_put_by_index:
+ case op_define_data_property:
+ case op_define_accessor_property:
case op_profile_type:
case op_profile_control_flow:
case op_put_to_arguments:
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1235,6 +1235,25 @@
out.printf("%s, %s, %d, %s", registerName(r0).data(), registerName(r1).data(), n0, registerName(r2).data());
break;
}
+ case op_define_data_property: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ int r3 = (++it)->u.operand;
+ printLocationAndOp(out, exec, location, it, "define_data_property");
+ out.printf("%s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data());
+ break;
+ }
+ case op_define_accessor_property: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int r2 = (++it)->u.operand;
+ int r3 = (++it)->u.operand;
+ int r4 = (++it)->u.operand;
+ printLocationAndOp(out, exec, location, it, "define_accessor_property");
+ out.printf("%s, %s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), registerName(r4).data());
+ break;
+ }
case op_del_by_id: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
Modified: trunk/Source/_javascript_Core/bytecode/SpecialPointer.h (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecode/SpecialPointer.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecode/SpecialPointer.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -41,7 +41,7 @@
} // namespace Special
enum class LinkTimeConstant {
- DefinePropertyFunction,
+ ThrowTypeErrorFunction,
};
const unsigned LinkTimeConstantCount = 1;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -35,6 +35,7 @@
#include "BuiltinExecutables.h"
#include "BytecodeGeneratorification.h"
#include "BytecodeLivenessAnalysis.h"
+#include "DefinePropertyAttributes.h"
#include "Interpreter.h"
#include "JSFunction.h"
#include "JSGeneratorFunction.h"
@@ -1543,6 +1544,9 @@
m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
}
+ if (!dst)
+ return m_linkTimeConstantRegisters[constantIndex];
+
emitOpcode(op_mov);
instructions().append(dst->index());
instructions().append(m_linkTimeConstantRegisters[constantIndex]->index());
@@ -3274,38 +3278,59 @@
}
void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
- RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
+ RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options)
{
- RefPtr<RegisterID> descriptorRegister = emitNewObject(newTemporary());
+ DefinePropertyAttributes attributes;
+ if (options & PropertyConfigurable)
+ attributes.setConfigurable(true);
- RefPtr<RegisterID> trueRegister = emitLoad(newTemporary(), true);
- if (options & PropertyConfigurable)
- emitDirectPutById(descriptorRegister.get(), propertyNames().configurable, trueRegister.get(), PropertyNode::Unknown);
if (options & PropertyWritable)
- emitDirectPutById(descriptorRegister.get(), propertyNames().writable, trueRegister.get(), PropertyNode::Unknown);
- else if (valueRegister) {
- RefPtr<RegisterID> falseRegister = emitLoad(newTemporary(), false);
- emitDirectPutById(descriptorRegister.get(), propertyNames().writable, falseRegister.get(), PropertyNode::Unknown);
- }
+ attributes.setWritable(true);
+ else if (valueRegister)
+ attributes.setWritable(false);
+
if (options & PropertyEnumerable)
- emitDirectPutById(descriptorRegister.get(), propertyNames().enumerable, trueRegister.get(), PropertyNode::Unknown);
+ attributes.setEnumerable(true);
if (valueRegister)
- emitDirectPutById(descriptorRegister.get(), propertyNames().value, valueRegister, PropertyNode::Unknown);
+ attributes.setValue();
if (getterRegister)
- emitDirectPutById(descriptorRegister.get(), propertyNames().get, getterRegister, PropertyNode::Unknown);
+ attributes.setGet();
if (setterRegister)
- emitDirectPutById(descriptorRegister.get(), propertyNames().set, setterRegister, PropertyNode::Unknown);
+ attributes.setSet();
- RefPtr<RegisterID> definePropertyRegister = emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction);
+ ASSERT(!valueRegister || (!getterRegister && !setterRegister));
- CallArguments callArguments(*this, nullptr, 3);
- emitLoad(callArguments.thisRegister(), jsUndefined());
- emitMove(callArguments.argumentRegister(0), newObj);
- emitMove(callArguments.argumentRegister(1), propertyNameRegister);
- emitMove(callArguments.argumentRegister(2), descriptorRegister.get());
+ if (attributes.hasGet() || attributes.hasSet()) {
+ RefPtr<RegisterID> throwTypeErrorFunction;
+ if (!attributes.hasGet() || !attributes.hasSet())
+ throwTypeErrorFunction = emitMoveLinkTimeConstant(nullptr, LinkTimeConstant::ThrowTypeErrorFunction);
- emitCall(newTemporary(), definePropertyRegister.get(), NoExpectedFunction, callArguments, position, position, position, DebuggableCall::No);
+ RefPtr<RegisterID> getter;
+ if (attributes.hasGet())
+ getter = getterRegister;
+ else
+ getter = throwTypeErrorFunction;
+
+ RefPtr<RegisterID> setter;
+ if (attributes.hasSet())
+ setter = setterRegister;
+ else
+ setter = throwTypeErrorFunction;
+
+ emitOpcode(op_define_accessor_property);
+ instructions().append(newObj->index());
+ instructions().append(propertyNameRegister->index());
+ instructions().append(getter->index());
+ instructions().append(setter->index());
+ instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index());
+ } else {
+ emitOpcode(op_define_data_property);
+ instructions().append(newObj->index());
+ instructions().append(propertyNameRegister->index());
+ instructions().append(valueRegister->index());
+ instructions().append(emitLoad(nullptr, jsNumber(attributes.rawRepresentation()))->index());
+ }
}
RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -588,7 +588,7 @@
PropertyEnumerable = 1 << 2,
};
void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
- RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
+ RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options);
void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -590,12 +590,12 @@
ASSERT(node.needsSuperBinding());
RefPtr<RegisterID> propertyNameRegister;
if (node.name())
- propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
+ propertyNameRegister = generator.emitLoad(nullptr, *node.name());
else
propertyNameRegister = generator.emitNode(node.m_expression);
generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
- generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
+ generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
return;
}
if (const auto* identifier = node.name()) {
@@ -605,7 +605,7 @@
return;
}
- RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
+ RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
generator.emitDirectPutByVal(newObj, index.get(), value.get());
return;
}
@@ -1623,7 +1623,7 @@
RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
+ RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
}
@@ -3609,12 +3609,12 @@
emitPutHomeObject(generator, constructor.get(), prototype.get());
}
- RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
+ RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
- BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
+ BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
- RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
- generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
+ RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
+ generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0);
if (m_staticMethods)
generator.emitNode(constructor.get(), m_staticMethods);
@@ -3876,7 +3876,7 @@
if (!optionalIndex)
generator.emitGetById(temp.get(), rhs, target.propertyName);
else {
- RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
+ RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
generator.emitGetByVal(temp.get(), rhs, index.get());
}
} else {
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -2656,6 +2656,11 @@
clobberWorld(node->origin.semantic, clobberLimit);
break;
}
+
+ case DefineDataProperty:
+ case DefineAccessorProperty:
+ clobberWorld(node->origin.semantic, clobberLimit);
+ break;
case In: {
// FIXME: We can determine when the property definitely exists based on abstract
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -4238,6 +4238,38 @@
NEXT_OPCODE(op_put_by_val_with_this);
}
+ case op_define_data_property: {
+ Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
+ Node* property = get(VirtualRegister(currentInstruction[2].u.operand));
+ Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
+ Node* attributes = get(VirtualRegister(currentInstruction[4].u.operand));
+
+ addVarArgChild(base);
+ addVarArgChild(property);
+ addVarArgChild(value);
+ addVarArgChild(attributes);
+ addToGraph(Node::VarArg, DefineDataProperty, OpInfo(0), OpInfo(0));
+
+ NEXT_OPCODE(op_define_data_property);
+ }
+
+ case op_define_accessor_property: {
+ Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
+ Node* property = get(VirtualRegister(currentInstruction[2].u.operand));
+ Node* getter = get(VirtualRegister(currentInstruction[3].u.operand));
+ Node* setter = get(VirtualRegister(currentInstruction[4].u.operand));
+ Node* attributes = get(VirtualRegister(currentInstruction[5].u.operand));
+
+ addVarArgChild(base);
+ addVarArgChild(property);
+ addVarArgChild(getter);
+ addVarArgChild(setter);
+ addVarArgChild(attributes);
+ addToGraph(Node::VarArg, DefineAccessorProperty, OpInfo(0), OpInfo(0));
+
+ NEXT_OPCODE(op_define_accessor_property);
+ }
+
case op_try_get_by_id:
case op_get_by_id:
case op_get_by_id_proto_load:
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -173,6 +173,8 @@
case op_put_getter_setter_by_id:
case op_put_getter_by_val:
case op_put_setter_by_val:
+ case op_define_data_property:
+ case op_define_accessor_property:
case op_del_by_id:
case op_del_by_val:
case op_jmp:
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -494,6 +494,8 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
case DeleteById:
case DeleteByVal:
case ArrayPush:
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -111,6 +111,8 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
case DeleteById:
case DeleteByVal:
case CheckStructure:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1657,6 +1657,39 @@
break;
}
+ case DefineDataProperty: {
+ fixEdge<CellUse>(m_graph.varArgChild(node, 0));
+ Edge& propertyEdge = m_graph.varArgChild(node, 1);
+ if (propertyEdge->shouldSpeculateSymbol())
+ fixEdge<SymbolUse>(propertyEdge);
+ else if (propertyEdge->shouldSpeculateStringIdent())
+ fixEdge<StringIdentUse>(propertyEdge);
+ else if (propertyEdge->shouldSpeculateString())
+ fixEdge<StringUse>(propertyEdge);
+ else
+ fixEdge<UntypedUse>(propertyEdge);
+ fixEdge<UntypedUse>(m_graph.varArgChild(node, 2));
+ fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 3));
+ break;
+ }
+
+ case DefineAccessorProperty: {
+ fixEdge<CellUse>(m_graph.varArgChild(node, 0));
+ Edge& propertyEdge = m_graph.varArgChild(node, 1);
+ if (propertyEdge->shouldSpeculateSymbol())
+ fixEdge<SymbolUse>(propertyEdge);
+ else if (propertyEdge->shouldSpeculateStringIdent())
+ fixEdge<StringIdentUse>(propertyEdge);
+ else if (propertyEdge->shouldSpeculateString())
+ fixEdge<StringUse>(propertyEdge);
+ else
+ fixEdge<UntypedUse>(propertyEdge);
+ fixEdge<CellUse>(m_graph.varArgChild(node, 2));
+ fixEdge<CellUse>(m_graph.varArgChild(node, 3));
+ fixEdge<KnownInt32Use>(m_graph.varArgChild(node, 4));
+ break;
+ }
+
#if !ASSERT_DISABLED
// Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
case SetArgument:
@@ -1726,8 +1759,6 @@
case GetByValWithThis:
case CompareEqPtr:
break;
-
- break;
#else
default:
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -198,6 +198,8 @@
macro(PutGetterSetterById, NodeMustGenerate) \
macro(PutGetterByVal, NodeMustGenerate) \
macro(PutSetterByVal, NodeMustGenerate) \
+ macro(DefineDataProperty, NodeMustGenerate | NodeHasVarArgs) \
+ macro(DefineAccessorProperty, NodeMustGenerate | NodeHasVarArgs) \
macro(DeleteById, NodeResultBoolean | NodeMustGenerate) \
macro(DeleteByVal, NodeResultBoolean | NodeMustGenerate) \
macro(CheckStructure, NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -38,6 +38,7 @@
#include "DFGToFTLDeferredCompilationCallback.h"
#include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
#include "DFGWorklist.h"
+#include "DefinePropertyAttributes.h"
#include "DirectArguments.h"
#include "FTLForOSREntryJITCode.h"
#include "FTLOSREntry.h"
@@ -994,6 +995,98 @@
putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
}
+ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
+{
+ PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
+ ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
+ if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
+ JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
+ else
+ base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
+}
+
+void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, void());
+ defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
+}
+
+void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier propertyName = property->toIdentifier(exec);
+ RETURN_IF_EXCEPTION(scope, void());
+ defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
+}
+
+void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
+}
+
+void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
+}
+
+ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
+{
+ PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
+ ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
+ if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
+ JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
+ else
+ base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
+}
+
+void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
+ RETURN_IF_EXCEPTION(scope, void());
+ defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
+}
+
+void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier propertyName = property->toIdentifier(exec);
+ RETURN_IF_EXCEPTION(scope, void());
+ defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
+}
+
+void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
+}
+
+void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
+}
+
char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
{
VM* vm = &exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -113,6 +113,14 @@
void JIT_OPERATION operationPutByIdWithThisStrict(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
void JIT_OPERATION operationPutByValWithThis(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
void JIT_OPERATION operationPutByValWithThisStrict(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
+void JIT_OPERATION operationDefineDataProperty(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineDataPropertyString(ExecState*, JSObject*, JSString*, EncodedJSValue, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, EncodedJSValue, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineDataPropertySymbol(ExecState*, JSObject*, Symbol*, EncodedJSValue, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineAccessorProperty(ExecState*, JSObject*, EncodedJSValue, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineAccessorPropertyString(ExecState*, JSObject*, JSString*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
+void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1041,6 +1041,8 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
case DFG::Jump:
case Branch:
case Switch:
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -213,6 +213,8 @@
case PutGetterSetterById:
case PutGetterByVal:
case PutSetterByVal:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
case CheckStructure:
case GetExecutable:
case GetButterfly:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -8644,6 +8644,165 @@
blessedBooleanResult(resultGPR, node);
}
+void SpeculativeJIT::compileDefineDataProperty(Node* node)
+{
+#if USE(JSVALUE64)
+ static_assert(GPRInfo::numberOfRegisters >= 5, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
+#else
+ static_assert(GPRInfo::numberOfRegisters >= 6, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
+#endif
+
+ SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 0));
+ GPRReg baseGPR = base.gpr();
+
+ JSValueOperand value(this, m_jit.graph().varArgChild(node, 2));
+ JSValueRegs valueRegs = value.jsValueRegs();
+
+ SpeculateInt32Operand attributes(this, m_jit.graph().varArgChild(node, 3));
+ GPRReg attributesGPR = attributes.gpr();
+
+ Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
+ switch (propertyEdge.useKind()) {
+ case StringUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRReg propertyGPR = property.gpr();
+ speculateString(propertyEdge, propertyGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineDataPropertyString, NoResult, baseGPR, propertyGPR, valueRegs, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case StringIdentUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRTemporary ident(this);
+
+ GPRReg propertyGPR = property.gpr();
+ GPRReg identGPR = ident.gpr();
+
+ speculateString(propertyEdge, propertyGPR);
+ speculateStringIdentAndLoadStorage(propertyEdge, propertyGPR, identGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineDataPropertyStringIdent, NoResult, baseGPR, identGPR, valueRegs, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case SymbolUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRReg propertyGPR = property.gpr();
+ speculateSymbol(propertyEdge, propertyGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineDataPropertySymbol, NoResult, baseGPR, propertyGPR, valueRegs, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case UntypedUse: {
+ JSValueOperand property(this, propertyEdge);
+ JSValueRegs propertyRegs = property.jsValueRegs();
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineDataProperty, NoResult, baseGPR, propertyRegs, valueRegs, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ noResult(node, UseChildrenCalledExplicitly);
+}
+
+void SpeculativeJIT::compileDefineAccessorProperty(Node* node)
+{
+#if USE(JSVALUE64)
+ static_assert(GPRInfo::numberOfRegisters >= 5, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
+#else
+ static_assert(GPRInfo::numberOfRegisters >= 6, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
+#endif
+
+ SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 0));
+ GPRReg baseGPR = base.gpr();
+
+ SpeculateCellOperand getter(this, m_jit.graph().varArgChild(node, 2));
+ GPRReg getterGPR = getter.gpr();
+
+ SpeculateCellOperand setter(this, m_jit.graph().varArgChild(node, 3));
+ GPRReg setterGPR = setter.gpr();
+
+ SpeculateInt32Operand attributes(this, m_jit.graph().varArgChild(node, 4));
+ GPRReg attributesGPR = attributes.gpr();
+
+ Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
+ switch (propertyEdge.useKind()) {
+ case StringUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRReg propertyGPR = property.gpr();
+ speculateString(propertyEdge, propertyGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineAccessorPropertyString, NoResult, baseGPR, propertyGPR, getterGPR, setterGPR, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case StringIdentUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRTemporary ident(this);
+
+ GPRReg propertyGPR = property.gpr();
+ GPRReg identGPR = ident.gpr();
+
+ speculateString(propertyEdge, propertyGPR);
+ speculateStringIdentAndLoadStorage(propertyEdge, propertyGPR, identGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineAccessorPropertyStringIdent, NoResult, baseGPR, identGPR, getterGPR, setterGPR, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case SymbolUse: {
+ SpeculateCellOperand property(this, propertyEdge);
+ GPRReg propertyGPR = property.gpr();
+ speculateSymbol(propertyEdge, propertyGPR);
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineAccessorPropertySymbol, NoResult, baseGPR, propertyGPR, getterGPR, setterGPR, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ case UntypedUse: {
+ JSValueOperand property(this, propertyEdge);
+ JSValueRegs propertyRegs = property.jsValueRegs();
+
+ useChildren(node);
+
+ flushRegisters();
+ callOperation(operationDefineAccessorProperty, NoResult, baseGPR, propertyRegs, getterGPR, setterGPR, attributesGPR);
+ m_jit.exceptionCheck();
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ noResult(node, UseChildrenCalledExplicitly);
+}
+
} } // namespace JSC::DFG
#endif
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1335,6 +1335,46 @@
m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4);
return appendCall(operation);
}
+ JITCompiler::Call callOperation(V_JITOperation_EOJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3.payloadGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJssJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOIJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOSymJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.payloadGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJOOZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJssOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOIOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOSymOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
JITCompiler::Call callOperation(V_JITOperation_EOJIUi operation, GPRReg arg1, GPRReg arg2, UniquedStringImpl* impl, unsigned value)
{
m_jit.setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(impl), TrustedImm32(value));
@@ -1779,7 +1819,46 @@
m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), arg3.payloadGPR(), arg3.tagGPR(), arg4.payloadGPR(), arg4.tagGPR());
return appendCall(operation);
}
-
+ JITCompiler::Call callOperation(V_JITOperation_EOJJZ operation, GPRReg arg1, JSValueRegs arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3.payloadGPR(), arg3.tagGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJssJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOIJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOSymJZ operation, GPRReg arg1, GPRReg arg2, JSValueRegs arg3, GPRReg arg4)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3.payloadGPR(), arg3.tagGPR(), arg4);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJOOZ operation, GPRReg arg1, JSValueRegs arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOJssOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOIOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
+ JITCompiler::Call callOperation(V_JITOperation_EOSymOOZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4, arg5);
+ return appendCall(operation);
+ }
JITCompiler::Call callOperation(V_JITOperation_EOJIUi operation, GPRReg arg1, JSValueRegs arg2, UniquedStringImpl* impl, unsigned value)
{
m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), TrustedImmPtr(impl), TrustedImm32(value));
@@ -2570,6 +2649,8 @@
void compileGetDynamicVar(Node*);
void compilePutDynamicVar(Node*);
void compileCompareEqPtr(Node*);
+ void compileDefineDataProperty(Node*);
+ void compileDefineAccessorProperty(Node*);
void moveTrueTo(GPRReg);
void moveFalseTo(GPRReg);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -4479,6 +4479,16 @@
break;
}
+ case DefineDataProperty: {
+ compileDefineDataProperty(node);
+ break;
+ }
+
+ case DefineAccessorProperty: {
+ compileDefineAccessorProperty(node);
+ break;
+ }
+
case GetGlobalLexicalVariable:
case GetGlobalVar: {
GPRTemporary resultPayload(this);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -4437,6 +4437,16 @@
break;
}
+ case DefineDataProperty: {
+ compileDefineDataProperty(node);
+ break;
+ }
+
+ case DefineAccessorProperty: {
+ compileDefineAccessorProperty(node);
+ break;
+ }
+
case GetGlobalLexicalVariable:
case GetGlobalVar: {
GPRTemporary result(this);
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -263,6 +263,8 @@
case CompareGreater:
case CompareGreaterEq:
case CompareStrictEq:
+ case DefineDataProperty:
+ case DefineAccessorProperty:
// These are OK.
break;
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -691,6 +691,12 @@
case PutByValWithThis:
compilePutByValWithThis();
break;
+ case DefineDataProperty:
+ compileDefineDataProperty();
+ break;
+ case DefineAccessorProperty:
+ compileDefineAccessorProperty();
+ break;
case ArrayPush:
compileArrayPush();
break;
@@ -2763,6 +2769,71 @@
vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis),
m_callFrame, base, thisValue, property, value);
}
+
+ void compileDefineDataProperty()
+ {
+ LValue base = lowCell(m_graph.varArgChild(m_node, 0));
+ LValue value = lowJSValue(m_graph.varArgChild(m_node, 2));
+ LValue attributes = lowInt32(m_graph.varArgChild(m_node, 3));
+ Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
+ switch (propertyEdge.useKind()) {
+ case StringUse: {
+ LValue property = lowString(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineDataPropertyString), m_callFrame, base, property, value, attributes);
+ break;
+ }
+ case StringIdentUse: {
+ LValue property = lowStringIdent(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineDataPropertyStringIdent), m_callFrame, base, property, value, attributes);
+ break;
+ }
+ case SymbolUse: {
+ LValue property = lowSymbol(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineDataPropertySymbol), m_callFrame, base, property, value, attributes);
+ break;
+ }
+ case UntypedUse: {
+ LValue property = lowJSValue(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineDataProperty), m_callFrame, base, property, value, attributes);
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
+
+ void compileDefineAccessorProperty()
+ {
+ LValue base = lowCell(m_graph.varArgChild(m_node, 0));
+ LValue getter = lowCell(m_graph.varArgChild(m_node, 2));
+ LValue setter = lowCell(m_graph.varArgChild(m_node, 3));
+ LValue attributes = lowInt32(m_graph.varArgChild(m_node, 4));
+ Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
+ switch (propertyEdge.useKind()) {
+ case StringUse: {
+ LValue property = lowString(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineAccessorPropertyString), m_callFrame, base, property, getter, setter, attributes);
+ break;
+ }
+ case StringIdentUse: {
+ LValue property = lowStringIdent(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineAccessorPropertyStringIdent), m_callFrame, base, property, getter, setter, attributes);
+ break;
+ }
+ case SymbolUse: {
+ LValue property = lowSymbol(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineAccessorPropertySymbol), m_callFrame, base, property, getter, setter, attributes);
+ break;
+ }
+ case UntypedUse: {
+ LValue property = lowJSValue(propertyEdge);
+ vmCall(Void, m_out.operation(operationDefineAccessorProperty), m_callFrame, base, property, getter, setter, attributes);
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
void compilePutById()
{
Modified: trunk/Source/_javascript_Core/jit/CCallHelpers.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/CCallHelpers.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/CCallHelpers.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -68,107 +68,6 @@
storePtr(scratch2, Address(scratch1NonArgGPR));
}
-#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
-void CCallHelpers::setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD)
-{
- if (!ASSERT_DISABLED) {
- RegisterSet destinations(destA, destB, destC, destD);
- ASSERT_WITH_MESSAGE(destinations.numberOfSetGPRs() == 4, "Destinations should not be aliased.");
- }
-
- typedef std::pair<GPRReg, GPRReg> RegPair;
- Vector<RegPair, 4> pairs;
-
- if (srcA != destA)
- pairs.append(std::make_pair(srcA, destA));
- if (srcB != destB)
- pairs.append(std::make_pair(srcB, destB));
- if (srcC != destC)
- pairs.append(std::make_pair(srcC, destC));
- if (srcD != destD)
- pairs.append(std::make_pair(srcD, destD));
-
-
-#if !ASSERT_DISABLED
- auto numUniqueSources = [&] () -> unsigned {
- RegisterSet set;
- for (auto& pair : pairs) {
- GPRReg source = pair.first;
- set.set(source);
- }
- return set.numberOfSetGPRs();
- };
-
- auto numUniqueDests = [&] () -> unsigned {
- RegisterSet set;
- for (auto& pair : pairs) {
- GPRReg dest = pair.second;
- set.set(dest);
- }
- return set.numberOfSetGPRs();
- };
-#endif
-
- while (pairs.size()) {
- RegisterSet freeDestinations;
- for (auto& pair : pairs) {
- GPRReg dest = pair.second;
- freeDestinations.set(dest);
- }
- for (auto& pair : pairs) {
- GPRReg source = pair.first;
- freeDestinations.clear(source);
- }
-
- if (freeDestinations.numberOfSetGPRs()) {
- bool madeMove = false;
- for (unsigned i = 0; i < pairs.size(); i++) {
- auto& pair = pairs[i];
- GPRReg source = pair.first;
- GPRReg dest = pair.second;
- if (freeDestinations.get(dest)) {
- move(source, dest);
- pairs.remove(i);
- madeMove = true;
- break;
- }
- }
- ASSERT_UNUSED(madeMove, madeMove);
- continue;
- }
-
- ASSERT(numUniqueDests() == numUniqueSources());
- ASSERT(numUniqueDests() == pairs.size());
- // The set of source and destination registers are equivalent sets. This means we don't have
- // any free destination registers that won't also clobber a source. We get around this by
- // exchanging registers.
-
- GPRReg source = pairs[0].first;
- GPRReg dest = pairs[0].second;
- swap(source, dest);
- pairs.remove(0);
-
- GPRReg newSource = source;
- for (auto& pair : pairs) {
- GPRReg source = pair.first;
- if (source == dest) {
- pair.first = newSource;
- break;
- }
- }
-
- // We may have introduced pairs that have the same source and destination. Remove those now.
- for (unsigned i = 0; i < pairs.size(); i++) {
- auto& pair = pairs[i];
- if (pair.first == pair.second) {
- pairs.remove(i);
- i--;
- }
- }
- }
-}
-#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
-
} // namespace JSC
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/jit/CCallHelpers.h (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/CCallHelpers.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/CCallHelpers.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -986,7 +986,14 @@
swap(destB, destC);
}
- void setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD);
+ void setupFourStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD)
+ {
+ setupStubArgsGPR<4>({ { destA, destB, destC, destD } }, { { srcA, srcB, srcC, srcD } });
+ }
+ void setupFiveStubArgsGPR(GPRReg destA, GPRReg destB, GPRReg destC, GPRReg destD, GPRReg destE, GPRReg srcA, GPRReg srcB, GPRReg srcC, GPRReg srcD, GPRReg srcE)
+ {
+ setupStubArgsGPR<5>({ { destA, destB, destC, destD, destE } }, { { srcA, srcB, srcC, srcD, srcE } });
+ }
#if CPU(X86_64) || CPU(ARM64)
template<FPRReg destA, FPRReg destB>
@@ -2183,6 +2190,12 @@
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
}
+ ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
+ {
+ setupFiveStubArgsGPR(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, GPRInfo::argumentGPR4, GPRInfo::argumentGPR5, arg1, arg2, arg3, arg4, arg5);
+ move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+ }
+
ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3, GPRReg arg4)
{
setupStubArguments134(arg1, arg3, arg4);
@@ -2471,6 +2484,105 @@
// Ready for a jump!
move(newFramePointer, stackPointerRegister);
}
+
+#if NUMBER_OF_ARGUMENT_REGISTERS >= 4
+ template<unsigned NumberOfRegisters>
+ void setupStubArgsGPR(std::array<GPRReg, NumberOfRegisters> destinations, std::array<GPRReg, NumberOfRegisters> sources)
+ {
+ if (!ASSERT_DISABLED) {
+ RegisterSet set;
+ for (GPRReg dest : destinations)
+ set.set(dest);
+ ASSERT_WITH_MESSAGE(set.numberOfSetGPRs() == NumberOfRegisters, "Destinations should not be aliased.");
+ }
+
+ typedef std::pair<GPRReg, GPRReg> RegPair;
+ Vector<RegPair, NumberOfRegisters> pairs;
+
+ for (unsigned i = 0; i < NumberOfRegisters; ++i) {
+ if (sources[i] != destinations[i])
+ pairs.append(std::make_pair(sources[i], destinations[i]));
+ }
+
+#if !ASSERT_DISABLED
+ auto numUniqueSources = [&] () -> unsigned {
+ RegisterSet set;
+ for (auto& pair : pairs) {
+ GPRReg source = pair.first;
+ set.set(source);
+ }
+ return set.numberOfSetGPRs();
+ };
+
+ auto numUniqueDests = [&] () -> unsigned {
+ RegisterSet set;
+ for (auto& pair : pairs) {
+ GPRReg dest = pair.second;
+ set.set(dest);
+ }
+ return set.numberOfSetGPRs();
+ };
+#endif
+
+ while (pairs.size()) {
+ RegisterSet freeDestinations;
+ for (auto& pair : pairs) {
+ GPRReg dest = pair.second;
+ freeDestinations.set(dest);
+ }
+ for (auto& pair : pairs) {
+ GPRReg source = pair.first;
+ freeDestinations.clear(source);
+ }
+
+ if (freeDestinations.numberOfSetGPRs()) {
+ bool madeMove = false;
+ for (unsigned i = 0; i < pairs.size(); i++) {
+ auto& pair = pairs[i];
+ GPRReg source = pair.first;
+ GPRReg dest = pair.second;
+ if (freeDestinations.get(dest)) {
+ move(source, dest);
+ pairs.remove(i);
+ madeMove = true;
+ break;
+ }
+ }
+ ASSERT_UNUSED(madeMove, madeMove);
+ continue;
+ }
+
+ ASSERT(numUniqueDests() == numUniqueSources());
+ ASSERT(numUniqueDests() == pairs.size());
+ // The set of source and destination registers are equivalent sets. This means we don't have
+ // any free destination registers that won't also clobber a source. We get around this by
+ // exchanging registers.
+
+ GPRReg source = pairs[0].first;
+ GPRReg dest = pairs[0].second;
+ swap(source, dest);
+ pairs.remove(0);
+
+ GPRReg newSource = source;
+ for (auto& pair : pairs) {
+ GPRReg source = pair.first;
+ if (source == dest) {
+ pair.first = newSource;
+ break;
+ }
+ }
+
+ // We may have introduced pairs that have the same source and destination. Remove those now.
+ for (unsigned i = 0; i < pairs.size(); i++) {
+ auto& pair = pairs[i];
+ if (pair.first == pair.second) {
+ pairs.remove(i);
+ i--;
+ }
+ }
+ }
+ }
+#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4
// These operations clobber all volatile registers. They assume that there is room on the top of
// stack to marshall call arguments.
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -322,6 +322,8 @@
DEFINE_OP(op_put_getter_setter_by_id)
DEFINE_OP(op_put_getter_by_val)
DEFINE_OP(op_put_setter_by_val)
+ DEFINE_OP(op_define_data_property)
+ DEFINE_OP(op_define_accessor_property)
DEFINE_OP(op_ret)
DEFINE_OP(op_rshift)
Modified: trunk/Source/_javascript_Core/jit/JIT.h (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/JIT.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -566,6 +566,8 @@
void emit_op_put_getter_setter_by_id(Instruction*);
void emit_op_put_getter_by_val(Instruction*);
void emit_op_put_setter_by_val(Instruction*);
+ void emit_op_define_data_property(Instruction*);
+ void emit_op_define_accessor_property(Instruction*);
void emit_op_ret(Instruction*);
void emit_op_rshift(Instruction*);
void emit_op_set_function_name(Instruction*);
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -58,6 +58,7 @@
class Register;
class Structure;
class StructureStubInfo;
+class Symbol;
class SymbolTable;
class WatchpointSet;
@@ -110,6 +111,7 @@
Ssi: StructureStubInfo*
St: Structure*
Symtab: SymbolTable*
+ Sym: Symbol*
T: StringImpl*
V: void
Vm: VM*
@@ -268,6 +270,14 @@
typedef void (JIT_OPERATION *V_JITOperation_ESsiJJI)(ExecState*, StructureStubInfo*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*);
typedef void (JIT_OPERATION *V_JITOperation_EJJJI)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, UniquedStringImpl*);
typedef void (JIT_OPERATION *V_JITOperation_EJJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, EncodedJSValue);
+typedef void (JIT_OPERATION *V_JITOperation_EOJJZ)(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOJssJZ)(ExecState*, JSObject*, JSString*, EncodedJSValue, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOIJZ)(ExecState*, JSObject*, UniquedStringImpl*, EncodedJSValue, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOSymJZ)(ExecState*, JSObject*, Symbol*, EncodedJSValue, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOJOOZ)(ExecState*, JSObject*, EncodedJSValue, JSObject*, JSObject*, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOJssOOZ)(ExecState*, JSObject*, JSString*, JSObject*, JSObject*, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOIOOZ)(ExecState*, JSObject*, UniquedStringImpl*, JSObject*, JSObject*, int32_t);
+typedef void (JIT_OPERATION *V_JITOperation_EOSymOOZ)(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t);
typedef void (JIT_OPERATION *V_JITOperation_EWs)(ExecState*, WatchpointSet*);
typedef void (JIT_OPERATION *V_JITOperation_EZ)(ExecState*, int32_t);
typedef void (JIT_OPERATION *V_JITOperation_EZJ)(ExecState*, int32_t, EncodedJSValue);
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1770,6 +1770,18 @@
return slowCases;
}
+void JIT::emit_op_define_data_property(Instruction* currentInstruction)
+{
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_define_data_property);
+ slowPathCall.call();
+}
+
+void JIT::emit_op_define_accessor_property(Instruction* currentInstruction)
+{
+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_define_accessor_property);
+ slowPathCall.call();
+}
+
} // namespace JSC
#endif // ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (206777 => 206778)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2016-10-04 19:31:24 UTC (rev 206778)
@@ -1458,6 +1458,18 @@
dispatch(5)
+_llint_op_define_data_property:
+ traceExecution()
+ callOpcodeSlowPath(_slow_path_define_data_property)
+ dispatch(5)
+
+
+_llint_op_define_accessor_property:
+ traceExecution()
+ callOpcodeSlowPath(_slow_path_define_accessor_property)
+ dispatch(6)
+
+
_llint_op_jtrue:
traceExecution()
jumpTrueOrFalse(
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -33,6 +33,7 @@
#include "ClonedArguments.h"
#include "CodeProfiling.h"
#include "CommonSlowPathsExceptions.h"
+#include "DefinePropertyAttributes.h"
#include "DirectArguments.h"
#include "Error.h"
#include "ErrorHandlingScope.h"
@@ -930,4 +931,39 @@
END();
}
+SLOW_PATH_DECL(slow_path_define_data_property)
+{
+ BEGIN();
+ JSObject* base = asObject(OP_C(1).jsValue());
+ JSValue property = OP_C(2).jsValue();
+ JSValue value = OP_C(3).jsValue();
+ JSValue attributes = OP_C(4).jsValue();
+ ASSERT(attributes.isInt32());
+
+ auto propertyName = property.toPropertyKey(exec);
+ CHECK_EXCEPTION();
+ PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
+ ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
+ base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
+ END();
+}
+
+SLOW_PATH_DECL(slow_path_define_accessor_property)
+{
+ BEGIN();
+ JSObject* base = asObject(OP_C(1).jsValue());
+ JSValue property = OP_C(2).jsValue();
+ JSValue getter = OP_C(3).jsValue();
+ JSValue setter = OP_C(4).jsValue();
+ JSValue attributes = OP_C(5).jsValue();
+ ASSERT(attributes.isInt32());
+
+ auto propertyName = property.toPropertyKey(exec);
+ CHECK_EXCEPTION();
+ PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
+ ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
+ base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
+ END();
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -256,5 +256,7 @@
SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val_with_this);
SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id_with_this);
SLOW_PATH_HIDDEN_DECL(slow_path_put_by_val_with_this);
+SLOW_PATH_HIDDEN_DECL(slow_path_define_data_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_define_accessor_property);
} // namespace JSC
Added: trunk/Source/_javascript_Core/runtime/DefinePropertyAttributes.h (0 => 206778)
--- trunk/Source/_javascript_Core/runtime/DefinePropertyAttributes.h (rev 0)
+++ trunk/Source/_javascript_Core/runtime/DefinePropertyAttributes.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Optional.h>
+#include <wtf/TriState.h>
+
+namespace JSC {
+
+class DefinePropertyAttributes {
+public:
+ static_assert(FalseTriState == 0, "FalseTriState is 0.");
+ static_assert(TrueTriState == 1, "TrueTriState is 1.");
+ static_assert(MixedTriState == 2, "MixedTriState is 2.");
+
+ static const unsigned ConfigurableShift = 0;
+ static const unsigned EnumerableShift = 2;
+ static const unsigned WritableShift = 4;
+ static const unsigned ValueShift = 6;
+ static const unsigned GetShift = 7;
+ static const unsigned SetShift = 8;
+
+ DefinePropertyAttributes()
+ : m_attributes(
+ (MixedTriState << ConfigurableShift)
+ | (MixedTriState << EnumerableShift)
+ | (MixedTriState << WritableShift)
+ | (0 << ValueShift)
+ | (0 << GetShift)
+ | (0 << SetShift))
+ {
+ }
+
+ explicit DefinePropertyAttributes(unsigned attributes)
+ : m_attributes(attributes)
+ {
+ }
+
+ unsigned rawRepresentation() const
+ {
+ return m_attributes;
+ }
+
+ bool hasValue() const
+ {
+ return m_attributes & (0b1 << ValueShift);
+ }
+
+ void setValue()
+ {
+ m_attributes = m_attributes | (0b1 << ValueShift);
+ }
+
+ bool hasGet() const
+ {
+ return m_attributes & (0b1 << GetShift);
+ }
+
+ void setGet()
+ {
+ m_attributes = m_attributes | (0b1 << GetShift);
+ }
+
+ bool hasSet() const
+ {
+ return m_attributes & (0b1 << SetShift);
+ }
+
+ void setSet()
+ {
+ m_attributes = m_attributes | (0b1 << SetShift);
+ }
+
+ bool hasWritable() const
+ {
+ return extractTriState(WritableShift) != MixedTriState;
+ }
+
+ Optional<bool> writable() const
+ {
+ if (!hasWritable())
+ return Nullopt;
+ return extractTriState(WritableShift) == TrueTriState;
+ }
+
+ bool hasConfigurable() const
+ {
+ return extractTriState(ConfigurableShift) != MixedTriState;
+ }
+
+ Optional<bool> configurable() const
+ {
+ if (!hasConfigurable())
+ return Nullopt;
+ return extractTriState(ConfigurableShift) == TrueTriState;
+ }
+
+ bool hasEnumerable() const
+ {
+ return extractTriState(EnumerableShift) != MixedTriState;
+ }
+
+ Optional<bool> enumerable() const
+ {
+ if (!hasEnumerable())
+ return Nullopt;
+ return extractTriState(EnumerableShift) == TrueTriState;
+ }
+
+ void setWritable(bool value)
+ {
+ fillWithTriState(value ? TrueTriState : FalseTriState, WritableShift);
+ }
+
+ void setConfigurable(bool value)
+ {
+ fillWithTriState(value ? TrueTriState : FalseTriState, ConfigurableShift);
+ }
+
+ void setEnumerable(bool value)
+ {
+ fillWithTriState(value ? TrueTriState : FalseTriState, EnumerableShift);
+ }
+
+private:
+ void fillWithTriState(TriState state, unsigned shift)
+ {
+ unsigned mask = 0b11 << shift;
+ m_attributes = (m_attributes & ~mask) | (state << shift);
+ }
+
+ TriState extractTriState(unsigned shift) const
+ {
+ return static_cast<TriState>((m_attributes >> shift) & 0b11);
+ }
+
+ unsigned m_attributes;
+};
+
+
+} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -404,7 +404,7 @@
m_functionProtoHasInstanceSymbolFunction.set(vm, this, hasInstanceSymbolFunction);
m_throwTypeErrorGetterSetter.initLater(
[] (const Initializer<GetterSetter>& init) {
- JSFunction* thrower = JSFunction::create(init.vm, init.owner, 0, String(), globalFuncThrowTypeError);
+ JSFunction* thrower = init.owner->throwTypeErrorFunction();
GetterSetter* getterSetter = GetterSetter::create(init.vm, init.owner);
getterSetter->setGetter(init.vm, init.owner, thrower);
getterSetter->setSetter(init.vm, init.owner, thrower);
@@ -581,8 +581,8 @@
ObjectConstructor* objectConstructor = ObjectConstructor::create(vm, this, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
m_objectConstructor.set(vm, this, objectConstructor);
- JSFunction* definePropertyFunction = m_objectConstructor->addDefineProperty(exec, this);
- m_definePropertyFunction.set(vm, this, definePropertyFunction);
+ JSFunction* throwTypeErrorFunction = JSFunction::create(vm, this, 0, String(), globalFuncThrowTypeError);
+ m_throwTypeErrorFunction.set(vm, this, throwTypeErrorFunction);
JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
ArrayConstructor* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get());
@@ -803,7 +803,7 @@
m_specialPointers[Special::ObjectConstructor] = objectConstructor;
m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
- m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::DefinePropertyFunction)] = m_definePropertyFunction.get();
+ m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::ThrowTypeErrorFunction)] = m_throwTypeErrorFunction.get();
if (UNLIKELY(Options::useDollarVM())) {
JSDollarVMPrototype* dollarVMPrototype = JSDollarVMPrototype::create(vm, this, JSDollarVMPrototype::createStructure(vm, this, m_objectPrototype.get()));
@@ -1066,7 +1066,7 @@
visitor.append(&thisObject->m_evalFunction);
visitor.append(&thisObject->m_callFunction);
visitor.append(&thisObject->m_applyFunction);
- visitor.append(&thisObject->m_definePropertyFunction);
+ visitor.append(&thisObject->m_throwTypeErrorFunction);
thisObject->m_arrayProtoToStringFunction.visit(visitor);
thisObject->m_arrayProtoValuesFunction.visit(visitor);
thisObject->m_initializePromiseFunction.visit(visitor);
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -233,7 +233,7 @@
WriteBarrier<JSFunction> m_evalFunction;
WriteBarrier<JSFunction> m_callFunction;
WriteBarrier<JSFunction> m_applyFunction;
- WriteBarrier<JSFunction> m_definePropertyFunction;
+ WriteBarrier<JSFunction> m_throwTypeErrorFunction;
LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoToStringFunction;
LazyProperty<JSGlobalObject, JSFunction> m_arrayProtoValuesFunction;
LazyProperty<JSGlobalObject, JSFunction> m_initializePromiseFunction;
@@ -478,7 +478,7 @@
JSFunction* evalFunction() const { return m_evalFunction.get(); }
JSFunction* callFunction() const { return m_callFunction.get(); }
JSFunction* applyFunction() const { return m_applyFunction.get(); }
- JSFunction* definePropertyFunction() const { return m_definePropertyFunction.get(); }
+ JSFunction* throwTypeErrorFunction() const { return m_throwTypeErrorFunction.get(); }
JSFunction* arrayProtoToStringFunction() const { return m_arrayProtoToStringFunction.get(this); }
JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(this); }
JSFunction* initializePromiseFunction() const { return m_initializePromiseFunction.get(this); }
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2016-10-04 19:31:24 UTC (rev 206778)
@@ -107,14 +107,6 @@
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyNamesPrivateName(), objectConstructorGetOwnPropertyNames, DontEnum, 1);
}
-JSFunction* ObjectConstructor::addDefineProperty(ExecState* exec, JSGlobalObject* globalObject)
-{
- VM& vm = exec->vm();
- JSFunction* definePropertyFunction = JSFunction::create(vm, globalObject, 3, vm.propertyNames->defineProperty.string(), objectConstructorDefineProperty);
- putDirectWithoutTransition(vm, vm.propertyNames->defineProperty, definePropertyFunction, DontEnum);
- return definePropertyFunction;
-}
-
// ES 19.1.1.1 Object([value])
static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSValue newTarget)
{
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.h (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -53,8 +53,6 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
- JSFunction* addDefineProperty(ExecState*, JSGlobalObject*);
-
protected:
void finishCreation(VM&, JSGlobalObject*, ObjectPrototype*);
Modified: trunk/Source/_javascript_Core/runtime/PropertyDescriptor.h (206777 => 206778)
--- trunk/Source/_javascript_Core/runtime/PropertyDescriptor.h 2016-10-04 19:00:06 UTC (rev 206777)
+++ trunk/Source/_javascript_Core/runtime/PropertyDescriptor.h 2016-10-04 19:31:24 UTC (rev 206778)
@@ -25,6 +25,7 @@
#pragma once
+#include "DefinePropertyAttributes.h"
#include "JSCJSValue.h"
namespace JSC {
@@ -92,4 +93,30 @@
unsigned m_seenAttributes;
};
-} // namespace JSC
+inline PropertyDescriptor toPropertyDescriptor(JSValue value, JSValue getter, JSValue setter, DefinePropertyAttributes attributes)
+{
+ // We assume that validation is already done.
+ PropertyDescriptor desc;
+
+ if (Optional<bool> enumerable = attributes.enumerable())
+ desc.setEnumerable(enumerable.value());
+
+ if (Optional<bool> configurable = attributes.configurable())
+ desc.setConfigurable(configurable.value());
+
+ if (attributes.hasValue())
+ desc.setValue(value);
+
+ if (Optional<bool> writable = attributes.writable())
+ desc.setWritable(writable.value());
+
+ if (attributes.hasGet())
+ desc.setGetter(getter);
+
+ if (attributes.hasSet())
+ desc.setSetter(setter);
+
+ return desc;
+}
+
+}