summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-27 21:51:42 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-27 21:51:42 +0200
commitbe01689f43cf6882cf670d33df49ead1f570c53a (patch)
tree4bb2161d8983b38e3e7ed37b4a50303bfd5e2e85 /Source/JavaScriptCore
parenta89b2ebb8e192c5e8cea21079bda2ee2c0c7dddd (diff)
downloadqtwebkit-be01689f43cf6882cf670d33df49ead1f570c53a.tar.gz
Imported WebKit commit 8d6c5efc74f0222dfc7bcce8d845d4a2707ed9e6 (http://svn.webkit.org/repository/webkit/trunk@118629)
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/API/JSCallbackConstructor.cpp2
-rw-r--r--Source/JavaScriptCore/API/JSCallbackObject.cpp4
-rw-r--r--Source/JavaScriptCore/ChangeLog220
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp7
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h6
-rw-r--r--Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp4
-rw-r--r--Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h2
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h2
-rw-r--r--Source/JavaScriptCore/bytecode/ValueProfile.h27
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp3
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp70
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp30
-rw-r--r--Source/JavaScriptCore/dfg/DFGCSEPhase.cpp263
-rw-r--r--Source/JavaScriptCore/dfg/DFGGraph.h6
-rw-r--r--Source/JavaScriptCore/dfg/DFGNode.h29
-rw-r--r--Source/JavaScriptCore/dfg/DFGNodeType.h24
-rw-r--r--Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp4
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp10
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp10
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp10
-rw-r--r--Source/JavaScriptCore/heap/MarkedBlock.cpp6
-rw-r--r--Source/JavaScriptCore/heap/WeakBlock.h10
-rw-r--r--Source/JavaScriptCore/heap/WeakSetInlines.h13
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes.cpp22
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes32_64.cpp29
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp2
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm6
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm6
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/NameInstance.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h7
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.cpp2
45 files changed, 761 insertions, 117 deletions
diff --git a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp
index c8b4c0659..8fd2b61f1 100644
--- a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp
+++ b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp
@@ -61,7 +61,7 @@ JSCallbackConstructor::~JSCallbackConstructor()
void JSCallbackConstructor::destroy(JSCell* cell)
{
- jsCast<JSCallbackConstructor*>(cell)->JSCallbackConstructor::~JSCallbackConstructor();
+ static_cast<JSCallbackConstructor*>(cell)->JSCallbackConstructor::~JSCallbackConstructor();
}
static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec)
diff --git a/Source/JavaScriptCore/API/JSCallbackObject.cpp b/Source/JavaScriptCore/API/JSCallbackObject.cpp
index 68c26824d..921d37897 100644
--- a/Source/JavaScriptCore/API/JSCallbackObject.cpp
+++ b/Source/JavaScriptCore/API/JSCallbackObject.cpp
@@ -54,13 +54,13 @@ Structure* JSCallbackObject<JSGlobalObject>::createStructure(JSGlobalData& globa
template <class Parent>
void JSCallbackObject<Parent>::destroy(JSCell* cell)
{
- jsCast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
+ static_cast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
}
void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
{
JSClassRef jsClass = static_cast<JSClassRef>(context);
- JSObjectRef thisRef = toRef(asObject(handle.get()));
+ JSObjectRef thisRef = toRef(static_cast<JSObject*>(handle.get().asCell()));
for (; jsClass; jsClass = jsClass->parentClass)
if (JSObjectFinalizeCallback finalize = jsClass->finalize)
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 7bea6a152..c80a45805 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,223 @@
+2012-05-26 Geoffrey Garen <ggaren@apple.com>
+
+ WebKit should be lazy-finalization-safe (esp. the DOM) v2
+ https://bugs.webkit.org/show_bug.cgi?id=87581
+
+ Reviewed by Oliver Hunt.
+
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::callDestructor):
+ * heap/WeakBlock.h:
+ * heap/WeakSetInlines.h:
+ (JSC::WeakBlock::finalize): Since we don't guarantee destruction order,
+ it's not valid to access GC pointers like the Structure pointer during
+ finalization. We NULL out the structure pointer in debug builds to try
+ to make this programming mistake more obvious.
+
+ * API/JSCallbackConstructor.cpp:
+ (JSC::JSCallbackConstructor::destroy):
+ * API/JSCallbackObject.cpp:
+ (JSC::::destroy):
+ (JSC::JSCallbackObjectData::finalize):
+ * runtime/Arguments.cpp:
+ (JSC::Arguments::destroy):
+ * runtime/DateInstance.cpp:
+ (JSC::DateInstance::destroy):
+ * runtime/Error.cpp:
+ (JSC::StrictModeTypeErrorFunction::destroy):
+ * runtime/Executable.cpp:
+ (JSC::ExecutableBase::destroy):
+ (JSC::NativeExecutable::destroy):
+ (JSC::ScriptExecutable::destroy):
+ (JSC::EvalExecutable::destroy):
+ (JSC::ProgramExecutable::destroy):
+ (JSC::FunctionExecutable::destroy):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::destroy):
+ * runtime/JSPropertyNameIterator.cpp:
+ (JSC::JSPropertyNameIterator::destroy):
+ * runtime/JSStaticScopeObject.cpp:
+ (JSC::JSStaticScopeObject::destroy):
+ * runtime/JSString.cpp:
+ (JSC::JSString::destroy):
+ * runtime/JSVariableObject.cpp:
+ (JSC::JSVariableObject::destroy):
+ * runtime/NameInstance.cpp:
+ (JSC::NameInstance::destroy):
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::destroy):
+ * runtime/RegExpConstructor.cpp:
+ (JSC::RegExpConstructor::destroy):
+ * runtime/Structure.cpp:
+ (JSC::Structure::destroy):
+ * runtime/StructureChain.cpp:
+ (JSC::StructureChain::destroy): Use static_cast instead of jsCast because
+ jsCast does Structure-based validation, and our Structure is not guaranteed
+ to be alive when we get finalized.
+
+2012-05-22 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CSE should eliminate redundant WeakJSConstants
+ https://bugs.webkit.org/show_bug.cgi?id=87179
+
+ Reviewed by Gavin Barraclough.
+
+ Merged r118141 from dfgopt.
+
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::weakConstantCSE):
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::weakConstant):
+
+2012-05-22 Filip Pizlo <fpizlo@apple.com>
+
+ DFG CSE should do redundant store elimination
+ https://bugs.webkit.org/show_bug.cgi?id=87161
+
+ Reviewed by Oliver Hunt.
+
+ Merge r118138 from dfgopt.
+
+ This patch adds redundant store elimination. For example, consider this
+ code:
+
+ o.x = 42;
+ o.x = 84;
+
+ If o.x is speculated to be a well-behaved field, the first assignment is
+ unnecessary, since the second just overwrites it. We would like to
+ eliminate the first assignment in these cases. The need for this
+ optimization arises mostly from stores that our runtime requires. For
+ example:
+
+ o = {f:1, g:2, h:3};
+
+ This will have four assignments to the structure for the newly created
+ object - one assignment for the empty structure, one for {f}, one for
+ {f, g}, and one for {f, g, h}. We would like to only have the last of
+ those assigments in this case.
+
+ Intriguingly, doing so for captured variables breaks the way arguments
+ simplification used to work. Consider that prior to either arguments
+ simplification or store elimination we will have IR that looks like:
+
+ a: SetLocal(r0, Empty)
+ b: SetLocal(r1, Empty)
+ c: GetLocal(r0)
+ d: CreateArguments(@c)
+ e: SetLocal(r0, @d)
+ f: SetLocal(r1, @d)
+
+ Then redundant store elimination will eliminate the stores that
+ initialize the arguments registers to Empty, but then arguments
+ simplification eliminates the stores that initialize the arguments to
+ the newly created arguments - and at this point we no longer have any
+ stores to the arguments register, leading to hilarious crashes. This
+ patch therefore changes arguments simplification to replace
+ CreateArguments with JSConstant(Empty) rather than eliminating the
+ SetLocals. But this revealed bugs where arguments simplification was
+ being overzealous, so I fixed those bugs.
+
+ This is a minor speed-up on V8/early and a handful of other tests.
+
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::uncheckedActivationRegister):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUse):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUses):
+ (JSC::DFG::ArgumentsSimplificationPhase::observeProperArgumentsUse):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::globalVarStoreElimination):
+ (CSEPhase):
+ (JSC::DFG::CSEPhase::putStructureStoreElimination):
+ (JSC::DFG::CSEPhase::putByOffsetStoreElimination):
+ (JSC::DFG::CSEPhase::setLocalStoreElimination):
+ (JSC::DFG::CSEPhase::setReplacement):
+ (JSC::DFG::CSEPhase::eliminate):
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::uncheckedActivationRegisterFor):
+ (Graph):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::isPhantomArguments):
+ (Node):
+ (JSC::DFG::Node::hasConstant):
+ (JSC::DFG::Node::valueOfJSConstant):
+ (JSC::DFG::Node::hasStructureTransitionData):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+
+2012-05-21 Filip Pizlo <fpizlo@apple.com>
+
+ DFG ConvertThis should just be a CheckStructure if the structure is known
+ https://bugs.webkit.org/show_bug.cgi?id=87057
+
+ Reviewed by Gavin Barraclough.
+
+ Merged r118021 from dfgopt.
+
+ This gives ValueProfile the ability to track singleton values - i.e. profiling
+ sites that always see the same value.
+
+ That is then used to profile the structure in op_convert_this.
+
+ This is then used to optimize op_convert_this into a CheckStructure if the
+ structure is always the same.
+
+ That then results in better CSE in inlined code that uses 'this', since
+ previously we couldn't CSE accesses on 'this' from different inline call frames.
+
+ Also fixed a bug where we were unnecessarily flushing 'this'.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ (JSC::CodeBlock::stronglyVisitStrongReferences):
+ * bytecode/LazyOperandValueProfile.cpp:
+ (JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
+ * bytecode/LazyOperandValueProfile.h:
+ (CompressedLazyOperandValueProfileHolder):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecode/ValueProfile.h:
+ (JSC::ValueProfileBase::ValueProfileBase):
+ (JSC::ValueProfileBase::dump):
+ (JSC::ValueProfileBase::computeUpdatedPrediction):
+ (ValueProfileBase):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::setArgument):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_convert_this):
+ (JSC::JIT::emitSlow_op_convert_this):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_convert_this):
+ (JSC::JIT::emitSlow_op_convert_this):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSValue.h:
+ (JSValue):
+ * runtime/Structure.h:
+ (JSC::JSValue::structureOrUndefined):
+ (JSC):
+
2012-05-24 Tim Horton <timothy_horton@apple.com>
Add feature defines for web-facing parts of CSS Regions and Exclusions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 6677b302b..e3ee2ed41 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -670,6 +670,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
case op_convert_this: {
int r0 = (++it)->u.operand;
dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data());
+ ++it; // Skip value profile.
break;
}
case op_new_object: {
@@ -2085,14 +2086,14 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
}
}
- m_lazyOperandValueProfiles.computeUpdatedPredictions();
+ m_lazyOperandValueProfiles.computeUpdatedPredictions(Collection);
#endif
#if ENABLE(VALUE_PROFILER)
for (unsigned profileIndex = 0; profileIndex < numberOfArgumentValueProfiles(); ++profileIndex)
- valueProfileForArgument(profileIndex)->computeUpdatedPrediction();
+ valueProfileForArgument(profileIndex)->computeUpdatedPrediction(Collection);
for (unsigned profileIndex = 0; profileIndex < numberOfValueProfiles(); ++profileIndex)
- valueProfile(profileIndex)->computeUpdatedPrediction();
+ valueProfile(profileIndex)->computeUpdatedPrediction(Collection);
#endif
}
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index c1772c3bf..ccaca3373 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -449,6 +449,12 @@ namespace JSC {
ASSERT(needsFullScopeChain());
return m_activationRegister;
}
+ int uncheckedActivationRegister()
+ {
+ if (!needsFullScopeChain())
+ return InvalidVirtualRegister;
+ return activationRegister();
+ }
bool usesArguments() const { return m_argumentsRegister != -1; }
bool needsActivation() const
diff --git a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
index f199b6923..695e21219 100644
--- a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
+++ b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.cpp
@@ -33,13 +33,13 @@ namespace JSC {
CompressedLazyOperandValueProfileHolder::CompressedLazyOperandValueProfileHolder() { }
CompressedLazyOperandValueProfileHolder::~CompressedLazyOperandValueProfileHolder() { }
-void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions()
+void CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions(OperationInProgress operation)
{
if (!m_data)
return;
for (unsigned i = 0; i < m_data->size(); ++i)
- m_data->at(i).computeUpdatedPrediction();
+ m_data->at(i).computeUpdatedPrediction(operation);
}
LazyOperandValueProfile* CompressedLazyOperandValueProfileHolder::add(
diff --git a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
index d0260f991..91e5314aa 100644
--- a/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
+++ b/Source/JavaScriptCore/bytecode/LazyOperandValueProfile.h
@@ -155,7 +155,7 @@ public:
CompressedLazyOperandValueProfileHolder();
~CompressedLazyOperandValueProfileHolder();
- void computeUpdatedPredictions();
+ void computeUpdatedPredictions(OperationInProgress);
LazyOperandValueProfile* add(const LazyOperandValueProfileKey& key);
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index ebf15bbd4..aa83d9b97 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -43,7 +43,7 @@ namespace JSC {
macro(op_init_lazy_reg, 2) \
macro(op_create_arguments, 2) \
macro(op_create_this, 2) \
- macro(op_convert_this, 2) \
+ macro(op_convert_this, 3) \
\
macro(op_new_object, 2) \
macro(op_new_array, 4) \
diff --git a/Source/JavaScriptCore/bytecode/ValueProfile.h b/Source/JavaScriptCore/bytecode/ValueProfile.h
index 73e363a8b..47fa8b72c 100644
--- a/Source/JavaScriptCore/bytecode/ValueProfile.h
+++ b/Source/JavaScriptCore/bytecode/ValueProfile.h
@@ -33,6 +33,7 @@
#if ENABLE(VALUE_PROFILER)
+#include "Heap.h"
#include "JSArray.h"
#include "PredictedType.h"
#include "Structure.h"
@@ -51,6 +52,7 @@ struct ValueProfileBase {
: m_bytecodeOffset(-1)
, m_prediction(PredictNone)
, m_numberOfSamplesInPrediction(0)
+ , m_singletonValueIsTop(false)
{
for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
m_buckets[i] = JSValue::encode(JSValue());
@@ -60,6 +62,7 @@ struct ValueProfileBase {
: m_bytecodeOffset(bytecodeOffset)
, m_prediction(PredictNone)
, m_numberOfSamplesInPrediction(0)
+ , m_singletonValueIsTop(false)
{
for (unsigned i = 0; i < totalNumberOfBuckets; ++i)
m_buckets[i] = JSValue::encode(JSValue());
@@ -112,6 +115,11 @@ struct ValueProfileBase {
"samples = %u, prediction = %s",
totalNumberOfSamples(),
predictionToString(m_prediction));
+ fprintf(out, ", value = ");
+ if (m_singletonValueIsTop)
+ fprintf(out, "TOP");
+ else
+ fprintf(out, "%s", m_singletonValue.description());
bool first = true;
for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
JSValue value = JSValue::decode(m_buckets[i]);
@@ -127,7 +135,7 @@ struct ValueProfileBase {
}
// Updates the prediction and returns the new one.
- PredictedType computeUpdatedPrediction()
+ PredictedType computeUpdatedPrediction(OperationInProgress operation = NoOperation)
{
for (unsigned i = 0; i < totalNumberOfBuckets; ++i) {
JSValue value = JSValue::decode(m_buckets[i]);
@@ -137,9 +145,23 @@ struct ValueProfileBase {
m_numberOfSamplesInPrediction++;
mergePrediction(m_prediction, predictionFromValue(value));
+ if (!m_singletonValueIsTop && !!value) {
+ if (!m_singletonValue)
+ m_singletonValue = value;
+ else if (m_singletonValue != value)
+ m_singletonValueIsTop = true;
+ }
+
m_buckets[i] = JSValue::encode(JSValue());
}
+ if (operation == Collection
+ && !m_singletonValueIsTop
+ && !!m_singletonValue
+ && m_singletonValue.isCell()
+ && !Heap::isMarked(m_singletonValue.asCell()))
+ m_singletonValueIsTop = true;
+
return m_prediction;
}
@@ -148,6 +170,9 @@ struct ValueProfileBase {
PredictedType m_prediction;
unsigned m_numberOfSamplesInPrediction;
+ bool m_singletonValueIsTop;
+ JSValue m_singletonValue;
+
EncodedJSValue m_buckets[totalNumberOfBuckets];
};
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 330750b61..fb05e48ff 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -445,8 +445,9 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
emitOpcode(op_create_this);
instructions().append(m_thisRegister.index());
} else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
- emitOpcode(op_convert_this);
+ ValueProfile* profile = emitProfiledOpcode(op_convert_this);
instructions().append(m_thisRegister.index());
+ instructions().append(profile);
}
}
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 33c058e7d..ff737cf1d 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -262,7 +262,8 @@ bool AbstractState::execute(unsigned indexInBlock)
switch (node.op()) {
case JSConstant:
- case WeakJSConstant: {
+ case WeakJSConstant:
+ case PhantomArguments: {
forNode(nodeIndex).set(m_graph.valueOfJSConstant(nodeIndex));
node.setCanExit(false);
break;
@@ -1403,6 +1404,7 @@ bool AbstractState::execute(unsigned indexInBlock)
}
case PutStructure:
+ case PhantomPutStructure:
node.setCanExit(false);
clobberStructures(indexInBlock);
forNode(node.child1()).set(node.structureTransitionData().newStructure);
diff --git a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
index 5ab515bd7..48163a91b 100644
--- a/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
@@ -283,6 +283,14 @@ public:
break;
}
+ case Phantom:
+ // We don't care about phantom uses, since phantom uses are all about
+ // just keeping things alive for OSR exit. If something - like the
+ // CreateArguments - is just being kept alive, then this transformation
+ // will not break this, since the Phantom will now just keep alive a
+ // PhantomArguments and OSR exit will still do the right things.
+ break;
+
default:
observeBadArgumentsUses(node);
break;
@@ -392,31 +400,6 @@ public:
VariableAccessData* variableAccessData = node.variableAccessData();
- // If this is a store into the arguments register for an InlineCallFrame*
- // that does not create arguments, then kill it.
- int argumentsRegister =
- m_graph.uncheckedArgumentsRegisterFor(node.codeOrigin);
- if ((variableAccessData->local() == argumentsRegister
- || variableAccessData->local()
- == unmodifiedArgumentsRegister(argumentsRegister))
- && !m_createsArguments.contains(source.codeOrigin.inlineCallFrame)) {
- // Find the Flush. It should be the next instruction.
- Node& flush = m_graph[block->at(indexInBlock + 1)];
- ASSERT(flush.op() == Flush);
- ASSERT(flush.variableAccessData() == variableAccessData);
- ASSERT(flush.child1() == nodeIndex);
- // Be defensive in release mode.
- if (flush.op() != Flush
- || flush.variableAccessData() != variableAccessData
- || flush.child1() != nodeIndex)
- break;
- flush.setOpAndDefaultFlags(Nop);
- m_graph.clearAndDerefChild1(flush);
- flush.setRefCount(0);
- changed = true;
- break;
- }
-
if (variableAccessData->isCaptured())
break;
@@ -583,6 +566,35 @@ public:
insertionSet.execute(*block);
}
+ for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+ BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+ if (!block)
+ continue;
+ for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block->at(indexInBlock);
+ Node& node = m_graph[nodeIndex];
+ if (!node.shouldGenerate())
+ continue;
+ if (node.op() != CreateArguments)
+ continue;
+ // If this is a CreateArguments for an InlineCallFrame* that does
+ // not create arguments, then replace it with a PhantomArguments.
+ // PhantomArguments is a constant that represents JSValue() (the
+ // empty value) in DFG and arguments creation for OSR exit.
+ if (m_createsArguments.contains(node.codeOrigin.inlineCallFrame))
+ continue;
+ Node phantom(Phantom, node.codeOrigin);
+ phantom.children = node.children;
+ phantom.ref();
+ node.setOpAndDefaultFlags(PhantomArguments);
+ node.children.reset();
+ NodeIndex phantomNodeIndex = m_graph.size();
+ m_graph.append(phantom);
+ insertionSet.append(indexInBlock, phantomNodeIndex);
+ }
+ insertionSet.execute(*block);
+ }
+
if (changed)
m_graph.collectGarbage();
@@ -659,9 +671,13 @@ private:
}
VariableAccessData* variableAccessData = child.variableAccessData();
- if (variableAccessData->isCaptured())
+ if (variableAccessData->isCaptured()) {
+ if (child.local() == m_graph.uncheckedArgumentsRegisterFor(child.codeOrigin)
+ && node.codeOrigin.inlineCallFrame != child.codeOrigin.inlineCallFrame)
+ m_createsArguments.add(child.codeOrigin.inlineCallFrame);
return;
-
+ }
+
ArgumentsAliasingData& data = m_argumentsAliasing.find(variableAccessData)->second;
data.mergeCallContext(node.codeOrigin.inlineCallFrame);
}
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 27e198c75..43157963c 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -350,8 +350,9 @@ private:
stack->m_argumentPositions[argument]->addVariable(variableAccessData);
NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value);
m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
- // Always flush arguments.
- addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
+ // Always flush arguments, except for 'this'.
+ if (argument)
+ addToGraph(Flush, OpInfo(variableAccessData), nodeIndex);
}
VariableAccessData* flushArgument(int operand)
@@ -1582,10 +1583,27 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_convert_this: {
NodeIndex op1 = getThis();
- if (m_graph[op1].op() == ConvertThis)
- setThis(op1);
- else
- setThis(addToGraph(ConvertThis, op1));
+ if (m_graph[op1].op() != ConvertThis) {
+ ValueProfile* profile =
+ m_inlineStackTop->m_profiledBlock->valueProfileForBytecodeOffset(m_currentProfilingIndex);
+ profile->computeUpdatedPrediction();
+#if DFG_ENABLE(DEBUG_VERBOSE)
+ dataLog("[@%lu bc#%u]: profile %p: ", m_graph.size(), m_currentProfilingIndex, profile);
+ profile->dump(WTF::dataFile());
+ dataLog("\n");
+#endif
+ if (profile->m_singletonValueIsTop
+ || !profile->m_singletonValue
+ || !profile->m_singletonValue.isCell()
+ || profile->m_singletonValue.asCell()->classInfo() != &Structure::s_info)
+ setThis(addToGraph(ConvertThis, op1));
+ else {
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(jsCast<Structure*>(profile->m_singletonValue.asCell()))),
+ op1);
+ }
+ }
NEXT_OPCODE(op_convert_this);
}
diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
index 842bcc236..3eeb70e05 100644
--- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
@@ -141,6 +141,22 @@ private:
return NoNode;
}
+ NodeIndex weakConstantCSE(Node& node)
+ {
+ for (unsigned i = endIndexForPureCSE(); i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ Node& otherNode = m_graph[index];
+ if (otherNode.op() != WeakJSConstant)
+ continue;
+
+ if (otherNode.weakConstant() != node.weakConstant())
+ continue;
+
+ return index;
+ }
+ return NoNode;
+ }
+
NodeIndex impureCSE(Node& node)
{
NodeIndex child1 = canonicalize(node.child1());
@@ -200,6 +216,33 @@ private:
return NoNode;
}
+ NodeIndex globalVarStoreElimination(unsigned varNumber, JSGlobalObject* globalObject)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ Node& node = m_graph[index];
+ if (!node.shouldGenerate())
+ continue;
+ switch (node.op()) {
+ case PutGlobalVar:
+ if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ return index;
+ break;
+
+ case GetGlobalVar:
+ if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject)
+ return NoNode;
+ break;
+
+ default:
+ break;
+ }
+ if (m_graph.clobbersWorld(index) || node.canExit())
+ return NoNode;
+ }
+ return NoNode;
+ }
+
NodeIndex getByValLoadElimination(NodeIndex child1, NodeIndex child2)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -304,6 +347,56 @@ private:
return false;
}
+ NodeIndex putStructureStoreElimination(NodeIndex child1)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ if (index == child1)
+ break;
+ Node& node = m_graph[index];
+ if (!node.shouldGenerate())
+ break;
+ switch (node.op()) {
+ case CheckStructure:
+ return NoNode;
+
+ case PhantomPutStructure:
+ if (node.child1() == child1) // No need to retrace our steps.
+ return NoNode;
+ break;
+
+ case PutStructure:
+ if (node.child1() == child1)
+ return index;
+ break;
+
+ // PutStructure needs to execute if we GC. Hence this needs to
+ // be careful with respect to nodes that GC.
+ case CreateArguments:
+ case TearOffArguments:
+ case NewFunctionNoCheck:
+ case NewFunction:
+ case NewFunctionExpression:
+ case CreateActivation:
+ case TearOffActivation:
+ case StrCat:
+ case ToPrimitive:
+ case NewRegexp:
+ case NewArrayBuffer:
+ case NewArray:
+ case NewObject:
+ case CreateThis:
+ return NoNode;
+
+ default:
+ break;
+ }
+ if (m_graph.clobbersWorld(index) || node.canExit())
+ return NoNode;
+ }
+ return NoNode;
+ }
+
NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -350,6 +443,52 @@ private:
return NoNode;
}
+ NodeIndex putByOffsetStoreElimination(unsigned identifierNumber, NodeIndex child1)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ if (index == child1)
+ break;
+
+ Node& node = m_graph[index];
+ if (!node.shouldGenerate())
+ continue;
+ switch (node.op()) {
+ case GetByOffset:
+ if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
+ return NoNode;
+ break;
+
+ case PutByOffset:
+ if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) {
+ if (node.child1() == child1) // Must be same property storage.
+ return index;
+ return NoNode;
+ }
+ break;
+
+ case PutByVal:
+ case PutByValAlias:
+ case GetByVal:
+ if (m_graph.byValIsPure(node)) {
+ // If PutByVal speculates that it's accessing an array with an
+ // integer index, then it's impossible for it to cause a structure
+ // change.
+ break;
+ }
+ return NoNode;
+
+ default:
+ if (m_graph.clobbersWorld(index))
+ return NoNode;
+ break;
+ }
+ if (node.canExit())
+ return NoNode;
+ }
+ return NoNode;
+ }
+
NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
{
for (unsigned i = m_indexInBlock; i--;) {
@@ -480,6 +619,58 @@ private:
return NoNode;
}
+ // This returns the Flush node that is keeping a SetLocal alive.
+ NodeIndex setLocalStoreElimination(VirtualRegister local)
+ {
+ for (unsigned i = m_indexInBlock; i--;) {
+ NodeIndex index = m_currentBlock->at(i);
+ Node& node = m_graph[index];
+ if (!node.shouldGenerate())
+ continue;
+ switch (node.op()) {
+ case GetLocal:
+ case SetLocal:
+ if (node.local() == local)
+ return NoNode;
+ break;
+
+ case GetLocalUnlinked:
+ if (node.unlinkedLocal() == local)
+ return NoNode;
+ break;
+
+ case Flush: {
+ if (node.local() != local)
+ break;
+ if (!i)
+ break;
+ NodeIndex prevIndex = m_currentBlock->at(i - 1);
+ if (prevIndex != node.child1().index())
+ break;
+ ASSERT(m_graph[prevIndex].local() == local);
+ ASSERT(m_graph[prevIndex].variableAccessData() == node.variableAccessData());
+ ASSERT(m_graph[prevIndex].shouldGenerate());
+ if (m_graph[prevIndex].refCount() > 1)
+ break;
+ return index;
+ }
+
+ case GetScopeChain:
+ if (m_graph.uncheckedActivationRegisterFor(node.codeOrigin) == local)
+ return NoNode;
+ break;
+
+ default:
+ if (m_graph.clobbersWorld(index))
+ return NoNode;
+ break;
+ }
+ if (node.canExit())
+ return NoNode;
+ }
+ return NoNode;
+ }
+
void performSubstitution(Edge& child, bool addRef = true)
{
// Check if this operand is actually unused.
@@ -501,14 +692,16 @@ private:
m_graph[child].ref();
}
- bool setReplacement(NodeIndex replacement)
+ enum PredictionHandlingMode { RequireSamePrediction, AllowPredictionMismatch };
+ bool setReplacement(NodeIndex replacement, PredictionHandlingMode predictionHandlingMode = RequireSamePrediction)
{
if (replacement == NoNode)
return false;
// Be safe. Don't try to perform replacements if the predictions don't
// agree.
- if (m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
+ if (predictionHandlingMode == RequireSamePrediction
+ && m_graph[m_compileIndex].prediction() != m_graph[replacement].prediction())
return false;
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
@@ -537,6 +730,17 @@ private:
node.setOpAndDefaultFlags(Phantom);
}
+ void eliminate(NodeIndex nodeIndex, NodeType phantomType = Phantom)
+ {
+ if (nodeIndex == NoNode)
+ return;
+ Node& node = m_graph[nodeIndex];
+ if (node.refCount() != 1)
+ return;
+ ASSERT(node.mustGenerate());
+ node.setOpAndDefaultFlags(phantomType);
+ }
+
void performNodeCSE(Node& node)
{
bool shouldGenerate = node.shouldGenerate();
@@ -622,6 +826,12 @@ private:
NodeIndex phiIndex = node.child1().index();
if (!setReplacement(possibleReplacement))
break;
+ // If the GetLocal we replaced used to refer to a SetLocal, then it now
+ // should refer to the child of the SetLocal instead.
+ if (m_graph[phiIndex].op() == SetLocal) {
+ ASSERT(node.child1().index() == phiIndex);
+ m_graph.changeEdge(node.children.child1(), m_graph[phiIndex].child1());
+ }
NodeIndex oldTailIndex = m_currentBlock->variablesAtTail.operand(
variableAccessData->local());
if (oldTailIndex == m_compileIndex) {
@@ -645,10 +855,39 @@ private:
break;
}
+ case SetLocal: {
+ if (m_fixpointState == FixpointNotConverged)
+ break;
+ VariableAccessData* variableAccessData = node.variableAccessData();
+ if (!variableAccessData->isCaptured())
+ break;
+ VirtualRegister local = variableAccessData->local();
+ NodeIndex replacementIndex = setLocalStoreElimination(local);
+ if (replacementIndex == NoNode)
+ break;
+ Node& replacement = m_graph[replacementIndex];
+ ASSERT(replacement.op() == Flush);
+ ASSERT(replacement.refCount() == 1);
+ ASSERT(replacement.shouldGenerate());
+ ASSERT(replacement.mustGenerate());
+ replacement.setOpAndDefaultFlags(Phantom);
+ NodeIndex setLocalIndex = replacement.child1().index();
+ ASSERT(m_graph[setLocalIndex].op() == SetLocal);
+ m_graph.clearAndDerefChild1(replacement);
+ replacement.children.child1() = m_graph[setLocalIndex].child1();
+ m_graph.ref(replacement.child1());
+ break;
+ }
+
case JSConstant:
// This is strange, but necessary. Some phases will convert nodes to constants,
// which may result in duplicated constants. We use CSE to clean this up.
- setReplacement(constantCSE(node));
+ setReplacement(constantCSE(node), AllowPredictionMismatch);
+ break;
+
+ case WeakJSConstant:
+ // FIXME: have CSE for weak constants against strong constants and vice-versa.
+ setReplacement(weakConstantCSE(node));
break;
case GetArrayLength:
@@ -681,6 +920,12 @@ private:
setReplacement(globalVarLoadElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
break;
+ case PutGlobalVar:
+ if (m_fixpointState == FixpointNotConverged)
+ break;
+ eliminate(globalVarStoreElimination(node.varNumber(), codeBlock()->globalObjectFor(node.codeOrigin)));
+ break;
+
case GetByVal:
if (m_graph.byValIsPure(node))
setReplacement(getByValLoadElimination(node.child1().index(), node.child2().index()));
@@ -697,6 +942,12 @@ private:
if (checkStructureLoadElimination(node.structureSet(), node.child1().index()))
eliminate();
break;
+
+ case PutStructure:
+ if (m_fixpointState == FixpointNotConverged)
+ break;
+ eliminate(putStructureStoreElimination(node.child1().index()), PhantomPutStructure);
+ break;
case CheckFunction:
if (checkFunctionElimination(node.function(), node.child1().index()))
@@ -718,6 +969,12 @@ private:
setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
break;
+ case PutByOffset:
+ if (m_fixpointState == FixpointNotConverged)
+ break;
+ eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1().index()));
+ break;
+
default:
// do nothing.
break;
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h
index 52654d23b..8ca3e2047 100644
--- a/Source/JavaScriptCore/dfg/DFGGraph.h
+++ b/Source/JavaScriptCore/dfg/DFGGraph.h
@@ -352,6 +352,12 @@ public:
codeOrigin.inlineCallFrame->stackOffset;
}
+ int uncheckedActivationRegisterFor(const CodeOrigin& codeOrigin)
+ {
+ ASSERT_UNUSED(codeOrigin, !codeOrigin.inlineCallFrame);
+ return m_codeBlock->uncheckedActivationRegister();
+ }
+
ValueProfile* valueProfileFor(NodeIndex nodeIndex)
{
if (nodeIndex == NoNode)
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index 1dbfccb8a..12ebba823 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -201,9 +201,21 @@ struct Node {
return op() == WeakJSConstant;
}
+ bool isPhantomArguments()
+ {
+ return op() == PhantomArguments;
+ }
+
bool hasConstant()
{
- return isConstant() || isWeakConstant();
+ switch (op()) {
+ case JSConstant:
+ case WeakJSConstant:
+ case PhantomArguments:
+ return true;
+ default:
+ return false;
+ }
}
unsigned constantNumber()
@@ -234,14 +246,23 @@ struct Node {
JSCell* weakConstant()
{
+ ASSERT(op() == WeakJSConstant);
return bitwise_cast<JSCell*>(m_opInfo);
}
JSValue valueOfJSConstant(CodeBlock* codeBlock)
{
- if (op() == WeakJSConstant)
+ switch (op()) {
+ case WeakJSConstant:
return JSValue(weakConstant());
- return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
+ case JSConstant:
+ return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
+ case PhantomArguments:
+ return JSValue();
+ default:
+ ASSERT_NOT_REACHED();
+ return JSValue(); // Have to return something in release mode.
+ }
}
bool isInt32Constant(CodeBlock* codeBlock)
@@ -589,7 +610,7 @@ struct Node {
bool hasStructureTransitionData()
{
- return op() == PutStructure;
+ return op() == PutStructure || op() == PhantomPutStructure;
}
StructureTransitionData& structureTransitionData()
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 091f96c6f..743f87955 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -37,11 +37,11 @@ namespace JSC { namespace DFG {
// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
#define FOR_EACH_DFG_OP(macro) \
/* A constant in the CodeBlock's constant pool. */\
- macro(JSConstant, NodeResultJS) \
+ macro(JSConstant, NodeResultJS | NodeDoesNotExit) \
\
/* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
/* code block. */\
- macro(WeakJSConstant, NodeResultJS) \
+ macro(WeakJSConstant, NodeResultJS | NodeDoesNotExit) \
\
/* Nodes for handling functions (both as call and as construct). */\
macro(ConvertThis, NodeResultJS) \
@@ -53,10 +53,10 @@ namespace JSC { namespace DFG {
/* VariableAccessData, and thus will share predictions. */\
macro(GetLocal, NodeResultJS) \
macro(SetLocal, 0) \
- macro(Phantom, NodeMustGenerate) \
- macro(Nop, 0) \
- macro(Phi, 0) \
- macro(Flush, NodeMustGenerate) \
+ macro(Phantom, NodeMustGenerate | NodeDoesNotExit) \
+ macro(Nop, 0 | NodeDoesNotExit) \
+ macro(Phi, 0 | NodeDoesNotExit) \
+ macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
\
/* Get the value of a local variable, without linking into the VariableAccessData */\
/* network. This is only valid for variable accesses whose predictions originated */\
@@ -64,12 +64,12 @@ namespace JSC { namespace DFG {
macro(GetLocalUnlinked, NodeResultJS) \
\
/* Marker for an argument being set at the prologue of a function. */\
- macro(SetArgument, 0) \
+ macro(SetArgument, 0 | NodeDoesNotExit) \
\
/* Hint that inlining begins here. No code is generated for this node. It's only */\
/* used for copying OSR data into inline frame data, to support reification of */\
/* call frames of inlined functions. */\
- macro(InlineStart, 0) \
+ macro(InlineStart, 0 | NodeDoesNotExit) \
\
/* Nodes for bitwise operations. */\
macro(BitAnd, NodeResultInt32) \
@@ -118,11 +118,12 @@ namespace JSC { namespace DFG {
macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
macro(CheckStructure, NodeMustGenerate) \
- macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
+ macro(PutStructure, NodeMustGenerate) \
+ macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \
macro(GetPropertyStorage, NodeResultStorage) \
macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \
macro(GetByOffset, NodeResultJS) \
- macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
+ macro(PutByOffset, NodeMustGenerate) \
macro(GetArrayLength, NodeResultInt32) \
macro(GetArgumentsLength, NodeResultInt32) \
macro(GetStringLength, NodeResultInt32) \
@@ -139,7 +140,7 @@ namespace JSC { namespace DFG {
macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
- macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
+ macro(PutGlobalVar, NodeMustGenerate) \
macro(CheckFunction, NodeMustGenerate) \
\
/* Optimizations for array mutation. */\
@@ -201,6 +202,7 @@ namespace JSC { namespace DFG {
/* Nodes used for arguments. Similar to activation support, only it makes even less */\
/* sense. */\
macro(CreateArguments, NodeResultJS) \
+ macro(PhantomArguments, NodeResultJS | NodeDoesNotExit) \
macro(TearOffArguments, NodeMustGenerate) \
macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate) \
macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate) \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index de01adb1f..75f0b7a74 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -618,7 +618,9 @@ private:
case DoubleAsInt32:
case GetLocalUnlinked:
case GetMyArgumentsLength:
- case GetMyArgumentByVal: {
+ case GetMyArgumentByVal:
+ case PhantomPutStructure:
+ case PhantomArguments: {
// This node should never be visible at this stage of compilation. It is
// inserted by fixup(), which follows this phase.
ASSERT_NOT_REACHED();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index db71fc01f..caa21aabf 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -1360,13 +1360,15 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo
return ValueRecovery::argumentsThatWereNotCreated();
case HaveNode: {
- if (isConstant(valueSource.nodeIndex()))
+ Node* nodePtr = &at(valueSource.nodeIndex());
+
+ if (nodePtr->isPhantomArguments())
+ return ValueRecovery::argumentsThatWereNotCreated();
+
+ if (nodePtr->hasConstant())
return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
- Node* nodePtr = &at(valueSource.nodeIndex());
if (!nodePtr->shouldGenerate()) {
- if (nodePtr->op() == CreateArguments)
- return ValueRecovery::argumentsThatWereNotCreated();
// It's legitimately dead. As in, nobody will ever use this node, or operand,
// ever. Set it to Undefined to make the GC happy after the OSR.
return ValueRecovery::constant(jsUndefined());
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 637e335a3..6c0093e41 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -1848,6 +1848,7 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ case PhantomArguments:
initConstantInfo(m_compileIndex);
break;
@@ -3429,6 +3430,15 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case PhantomPutStructure: {
+ m_jit.addWeakReferenceTransition(
+ node.codeOrigin.codeOriginOwner(),
+ node.structureTransitionData().previousStructure,
+ node.structureTransitionData().newStructure);
+ noResult(m_compileIndex);
+ break;
+ }
+
case PutStructure: {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 543e2b913..e4939b23a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -1924,6 +1924,7 @@ void SpeculativeJIT::compile(Node& node)
switch (op) {
case JSConstant:
+ case PhantomArguments:
initConstantInfo(m_compileIndex);
break;
@@ -3463,6 +3464,15 @@ void SpeculativeJIT::compile(Node& node)
break;
}
+ case PhantomPutStructure: {
+ m_jit.addWeakReferenceTransition(
+ node.codeOrigin.codeOriginOwner(),
+ node.structureTransitionData().previousStructure,
+ node.structureTransitionData().newStructure);
+ noResult(m_compileIndex);
+ break;
+ }
+
case PutStructure: {
SpeculateCellOperand base(this, node.child1());
GPRReg baseGPR = base.gpr();
diff --git a/Source/JavaScriptCore/heap/MarkedBlock.cpp b/Source/JavaScriptCore/heap/MarkedBlock.cpp
index 42dc10371..0075f78d7 100644
--- a/Source/JavaScriptCore/heap/MarkedBlock.cpp
+++ b/Source/JavaScriptCore/heap/MarkedBlock.cpp
@@ -67,8 +67,12 @@ inline void MarkedBlock::callDestructor(JSCell* cell)
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_heap->m_destroyedTypeCounts.countVPtr(vptr);
#endif
- cell->methodTable()->destroy(cell);
+#if !ASSERT_DISABLED || ENABLE(GC_VALIDATION)
+ cell->clearStructure();
+#endif
+
+ cell->methodTable()->destroy(cell);
cell->zap();
}
diff --git a/Source/JavaScriptCore/heap/WeakBlock.h b/Source/JavaScriptCore/heap/WeakBlock.h
index dc3e89d55..6461f7b2f 100644
--- a/Source/JavaScriptCore/heap/WeakBlock.h
+++ b/Source/JavaScriptCore/heap/WeakBlock.h
@@ -115,16 +115,6 @@ inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl)
return reinterpret_cast<FreeCell*>(weakImpl);
}
-inline void WeakBlock::finalize(WeakImpl* weakImpl)
-{
- ASSERT(weakImpl->state() == WeakImpl::Dead);
- weakImpl->setState(WeakImpl::Finalized);
- WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
- if (!weakHandleOwner)
- return;
- weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context());
-}
-
inline WeakImpl* WeakBlock::weakImpls()
{
return reinterpret_cast<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl));
diff --git a/Source/JavaScriptCore/heap/WeakSetInlines.h b/Source/JavaScriptCore/heap/WeakSetInlines.h
index 6e2420c45..c1c87b380 100644
--- a/Source/JavaScriptCore/heap/WeakSetInlines.h
+++ b/Source/JavaScriptCore/heap/WeakSetInlines.h
@@ -42,6 +42,19 @@ inline WeakImpl* WeakSet::allocate(JSValue jsValue, WeakHandleOwner* weakHandleO
return new (NotNull, weakImpl) WeakImpl(jsValue, weakHandleOwner, context);
}
+inline void WeakBlock::finalize(WeakImpl* weakImpl)
+{
+ ASSERT(weakImpl->state() == WeakImpl::Dead);
+ weakImpl->setState(WeakImpl::Finalized);
+ WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
+ if (!weakHandleOwner)
+ return;
+#if !ASSERT_DISABLED || ENABLE(GC_VALIDATION)
+ weakImpl->jsValue().asCell()->clearStructure();
+#endif
+ weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context());
+}
+
} // namespace JSC
#endif // WeakSetInlines_h
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index d458f7fb5..aa2938cc2 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1257,10 +1257,14 @@ void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)
void JIT::emit_op_convert_this(Instruction* currentInstruction)
{
- emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+ emitGetVirtualRegister(currentInstruction[1].u.operand, regT1);
- emitJumpSlowCaseIfNotJSCell(regT0);
- addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+ emitJumpSlowCaseIfNotJSCell(regT1);
+ if (shouldEmitProfiling()) {
+ loadPtr(Address(regT1, JSCell::structureOffset()), regT0);
+ emitValueProfilingSite();
+ }
+ addSlowCase(branchPtr(Equal, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
}
void JIT::emit_op_create_this(Instruction* currentInstruction)
@@ -1315,15 +1319,21 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC
void* globalThis = m_codeBlock->globalObject()->globalScopeChain()->globalThis.get();
linkSlowCase(iter);
- Jump isNotUndefined = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsUndefined())));
+ if (shouldEmitProfiling())
+ move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(jsUndefined()))), regT0);
+ Jump isNotUndefined = branchPtr(NotEqual, regT1, TrustedImmPtr(JSValue::encode(jsUndefined())));
+ emitValueProfilingSite();
move(TrustedImmPtr(globalThis), regT0);
emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
- isNotUndefined.link(this);
linkSlowCase(iter);
+ if (shouldEmitProfiling())
+ move(TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(m_globalData->stringStructure.get()))), regT0);
+ isNotUndefined.link(this);
+ emitValueProfilingSite();
JITStubCall stubCall(this, cti_op_convert_this);
- stubCall.addArgument(regT0);
+ stubCall.addArgument(regT1);
stubCall.call(currentInstruction[1].u.operand);
}
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 5643fe9f3..12e47b2ee 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1548,12 +1548,15 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
{
unsigned thisRegister = currentInstruction[1].u.operand;
- emitLoad(thisRegister, regT1, regT0);
+ emitLoad(thisRegister, regT3, regT2);
- addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
- addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
-
- map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
+ addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
+ if (shouldEmitProfiling()) {
+ loadPtr(Address(regT2, JSCell::structureOffset()), regT0);
+ move(regT3, regT1);
+ emitValueProfilingSite();
+ }
+ addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
}
void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1562,16 +1565,26 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC
unsigned thisRegister = currentInstruction[1].u.operand;
linkSlowCase(iter);
- Jump isNotUndefined = branch32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag));
+ if (shouldEmitProfiling()) {
+ move(TrustedImm32(JSValue::UndefinedTag), regT1);
+ move(TrustedImm32(0), regT0);
+ }
+ Jump isNotUndefined = branch32(NotEqual, regT3, TrustedImm32(JSValue::UndefinedTag));
+ emitValueProfilingSite();
move(TrustedImmPtr(globalThis), regT0);
move(TrustedImm32(JSValue::CellTag), regT1);
emitStore(thisRegister, regT1, regT0);
emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_convert_this));
- isNotUndefined.link(this);
linkSlowCase(iter);
+ if (shouldEmitProfiling()) {
+ move(TrustedImm32(JSValue::CellTag), regT1);
+ move(TrustedImmPtr(m_globalData->stringStructure.get()), regT0);
+ }
+ isNotUndefined.link(this);
+ emitValueProfilingSite();
JITStubCall stubCall(this, cti_op_convert_this);
- stubCall.addArgument(regT1, regT0);
+ stubCall.addArgument(regT3, regT2);
stubCall.call(thisRegister);
}
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index 066530c87..5cba5ea70 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -467,6 +467,8 @@ LLINT_SLOW_PATH_DECL(slow_path_convert_this)
LLINT_BEGIN();
JSValue v1 = LLINT_OP(1).jsValue();
ASSERT(v1.isPrimitive());
+ pc[OPCODE_LENGTH(op_convert_this) - 1].u.profile->m_buckets[0] =
+ JSValue::encode(v1.structureOrUndefined());
LLINT_RETURN(v1.toThisObject(exec));
}
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index e1b08eaa5..dd5ab674a 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -364,11 +364,13 @@ _llint_op_convert_this:
loadi PayloadOffset[cfr, t0, 8], t0
loadp JSCell::m_structure[t0], t0
bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
- dispatch(2)
+ loadi 8[PC], t1
+ valueProfile(CellTag, t0, t1)
+ dispatch(3)
.opConvertThisSlow:
callSlowPath(_llint_slow_path_convert_this)
- dispatch(2)
+ dispatch(3)
_llint_op_new_object:
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index a73085f76..5225bdda9 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -241,11 +241,13 @@ _llint_op_convert_this:
btpnz t0, tagMask, .opConvertThisSlow
loadp JSCell::m_structure[t0], t0
bbb Structure::m_typeInfo + TypeInfo::m_type[t0], ObjectType, .opConvertThisSlow
- dispatch(2)
+ loadp 16[PB, PC, 8], t1
+ valueProfile(t0, t1)
+ dispatch(3)
.opConvertThisSlow:
callSlowPath(_llint_slow_path_convert_this)
- dispatch(2)
+ dispatch(3)
_llint_op_new_object:
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index 4628cec8d..96791c326 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -54,7 +54,7 @@ void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor)
void Arguments::destroy(JSCell* cell)
{
- jsCast<Arguments*>(cell)->Arguments::~Arguments();
+ static_cast<Arguments*>(cell)->Arguments::~Arguments();
}
void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp
index a502770c8..47a19df47 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.cpp
+++ b/Source/JavaScriptCore/runtime/DateInstance.cpp
@@ -55,7 +55,7 @@ void DateInstance::finishCreation(JSGlobalData& globalData, double time)
void DateInstance::destroy(JSCell* cell)
{
- jsCast<DateInstance*>(cell)->DateInstance::~DateInstance();
+ static_cast<DateInstance*>(cell)->DateInstance::~DateInstance();
}
const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index bae07448b..a3a990d59 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -183,7 +183,7 @@ const ClassInfo StrictModeTypeErrorFunction::s_info = { "Function", &Base::s_inf
void StrictModeTypeErrorFunction::destroy(JSCell* cell)
{
- jsCast<StrictModeTypeErrorFunction*>(cell)->StrictModeTypeErrorFunction::~StrictModeTypeErrorFunction();
+ static_cast<StrictModeTypeErrorFunction*>(cell)->StrictModeTypeErrorFunction::~StrictModeTypeErrorFunction();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 0a6425a59..0ada2cb0f 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -43,7 +43,7 @@ const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_
#if ENABLE(JIT)
void ExecutableBase::destroy(JSCell* cell)
{
- jsCast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
+ static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
}
#endif
@@ -73,7 +73,7 @@ const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase
#if ENABLE(JIT)
void NativeExecutable::destroy(JSCell* cell)
{
- jsCast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
+ static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
}
#endif
@@ -108,7 +108,7 @@ const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase
#if ENABLE(JIT)
void ScriptExecutable::destroy(JSCell* cell)
{
- jsCast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
+ static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
}
#endif
@@ -121,7 +121,7 @@ EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool i
void EvalExecutable::destroy(JSCell* cell)
{
- jsCast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
+ static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
}
const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
@@ -133,7 +133,7 @@ ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
void ProgramExecutable::destroy(JSCell* cell)
{
- jsCast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
+ static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
}
const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
@@ -166,7 +166,7 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name,
void FunctionExecutable::destroy(JSCell* cell)
{
- jsCast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
+ static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
}
JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 2a4231537..8c8aa9079 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -127,7 +127,7 @@ JSGlobalObject::~JSGlobalObject()
void JSGlobalObject::destroy(JSCell* cell)
{
- jsCast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
+ static_cast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
}
void JSGlobalObject::init(JSObject* thisValue)
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index 6fd8b770b..6ceb3c411 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -83,7 +83,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
void JSPropertyNameIterator::destroy(JSCell* cell)
{
- jsCast<JSPropertyNameIterator*>(cell)->JSPropertyNameIterator::~JSPropertyNameIterator();
+ static_cast<JSPropertyNameIterator*>(cell)->JSPropertyNameIterator::~JSPropertyNameIterator();
}
JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index fc4c27bab..e5e65673c 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -36,7 +36,7 @@ const ClassInfo JSStaticScopeObject::s_info = { "Object", &Base::s_info, 0, 0, C
void JSStaticScopeObject::destroy(JSCell* cell)
{
- jsCast<JSStaticScopeObject*>(cell)->JSStaticScopeObject::~JSStaticScopeObject();
+ static_cast<JSStaticScopeObject*>(cell)->JSStaticScopeObject::~JSStaticScopeObject();
}
void JSStaticScopeObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index ad6bd3812..180c64b8b 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -47,7 +47,7 @@ void JSRopeString::RopeBuilder::expand()
void JSString::destroy(JSCell* cell)
{
- JSString* thisObject = jsCast<JSString*>(cell);
+ JSString* thisObject = static_cast<JSString*>(cell);
thisObject->JSString::~JSString();
}
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index 27046097c..f74bfad90 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -239,6 +239,8 @@ namespace JSC {
bool isCell() const;
JSCell* asCell() const;
JS_EXPORT_PRIVATE bool isValidCallee();
+
+ JSValue structureOrUndefined() const;
char* description() const;
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index eb9dfd4be..9dcbead34 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -39,7 +39,7 @@ namespace JSC {
void JSVariableObject::destroy(JSCell* cell)
{
- jsCast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
+ static_cast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
}
bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
diff --git a/Source/JavaScriptCore/runtime/NameInstance.cpp b/Source/JavaScriptCore/runtime/NameInstance.cpp
index aae290cb2..410fe62e7 100644
--- a/Source/JavaScriptCore/runtime/NameInstance.cpp
+++ b/Source/JavaScriptCore/runtime/NameInstance.cpp
@@ -38,7 +38,7 @@ NameInstance::NameInstance(JSGlobalData& globalData, Structure* structure, JSStr
void NameInstance::destroy(JSCell* cell)
{
- jsCast<NameInstance*>(cell)->NameInstance::~NameInstance();
+ static_cast<NameInstance*>(cell)->NameInstance::~NameInstance();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index b0f67607e..64e553be1 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -243,7 +243,7 @@ void RegExp::finishCreation(JSGlobalData& globalData)
void RegExp::destroy(JSCell* cell)
{
- RegExp* thisObject = jsCast<RegExp*>(cell);
+ RegExp* thisObject = static_cast<RegExp*>(cell);
#if REGEXP_FUNC_TEST_DATA_GEN
RegExpFunctionalTestCollector::get()->clearRegExp(this);
#endif
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 2c0f0c000..0f2091c27 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -104,7 +104,7 @@ void RegExpConstructor::finishCreation(ExecState* exec, RegExpPrototype* regExpP
void RegExpConstructor::destroy(JSCell* cell)
{
- jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
+ static_cast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
}
void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index b22deb0fa..dc4239799 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -216,7 +216,7 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
void Structure::destroy(JSCell* cell)
{
- jsCast<Structure*>(cell)->Structure::~Structure();
+ static_cast<Structure*>(cell)->Structure::~Structure();
}
void Structure::materializePropertyMap(JSGlobalData& globalData)
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 74336a288..f67c4e7f7 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -332,6 +332,13 @@ namespace JSC {
return entry ? entry->offset : notFound;
}
+ inline JSValue JSValue::structureOrUndefined() const
+ {
+ if (isCell())
+ return JSValue(asCell()->structure());
+ return jsUndefined();
+ }
+
inline bool JSCell::isObject() const
{
return m_structure->isObject();
diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp
index afb2d9501..a1c97340e 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.cpp
+++ b/Source/JavaScriptCore/runtime/StructureChain.cpp
@@ -41,7 +41,7 @@ StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure)
void StructureChain::destroy(JSCell* cell)
{
- jsCast<StructureChain*>(cell)->StructureChain::~StructureChain();
+ static_cast<StructureChain*>(cell)->StructureChain::~StructureChain();
}
void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor)