Commit 410b541c authored by oliver@apple.com's avatar oliver@apple.com
Browse files

fourthTier: CodeBlock should be RefCounted

https://bugs.webkit.org/show_bug.cgi?id=115594

Reviewed by Geoffrey Garen.

This makes it possible to have the currently-being-compiled CodeBlock not be
installed in Executable, while also allowing it to point to its intended
alternative(). So long as we were using ownership and not reference counting, it
would have been difficult to have both CodeBlock::m_alternative and
Executable::m_codeBlockForBlah point to the previous CodeBlock.

I also took the opportunity to clean up a bunch of code that appears to have
rotted.

* assembler/MacroAssemblerCodeRef.h:
(MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::operator==):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::releaseAlternative):
(JSC::CodeBlock::setAlternative):
(CodeBlock):
(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::ProgramCodeBlock::ProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):
* heap/DFGCodeBlocks.cpp:
(JSC::DFGCodeBlocks::~DFGCodeBlocks):
(JSC::DFGCodeBlocks::jettison):
(JSC::DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks):
* heap/DFGCodeBlocks.h:
(DFGCodeBlocks):
* heap/Heap.cpp:
(JSC::Heap::jettisonDFGCodeBlock):
* heap/Heap.h:
* jit/JITDriver.h:
(JSC::jitCompileIfAppropriate):
(JSC::jitCompileFunctionIfAppropriate):
* runtime/Executable.cpp:
(JSC::jettisonCodeBlock):
(JSC::EvalExecutable::jitCompile):
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::jitCompile):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::jitCompileForCall):
(JSC::FunctionExecutable::jitCompileForConstruct):
(JSC::FunctionExecutable::produceCodeBlockFor):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
* runtime/Executable.h:
(EvalExecutable):
(FunctionExecutable):
(JSC::FunctionExecutable::codeBlockFor):
* runtime/ExecutionHarness.h:
(JSC::prepareForExecution):
(JSC::prepareFunctionForExecution):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153147 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 98fb6bf1
2013-05-09 Filip Pizlo <fpizlo@apple.com>
fourthTier: CodeBlock should be RefCounted
https://bugs.webkit.org/show_bug.cgi?id=115594
Reviewed by Geoffrey Garen.
This makes it possible to have the currently-being-compiled CodeBlock not be
installed in Executable, while also allowing it to point to its intended
alternative(). So long as we were using ownership and not reference counting, it
would have been difficult to have both CodeBlock::m_alternative and
Executable::m_codeBlockForBlah point to the previous CodeBlock.
I also took the opportunity to clean up a bunch of code that appears to have
rotted.
* assembler/MacroAssemblerCodeRef.h:
(MacroAssemblerCodePtr):
(JSC::MacroAssemblerCodePtr::operator==):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::releaseAlternative):
(JSC::CodeBlock::setAlternative):
(CodeBlock):
(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::ProgramCodeBlock::ProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):
* heap/DFGCodeBlocks.cpp:
(JSC::DFGCodeBlocks::~DFGCodeBlocks):
(JSC::DFGCodeBlocks::jettison):
(JSC::DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks):
* heap/DFGCodeBlocks.h:
(DFGCodeBlocks):
* heap/Heap.cpp:
(JSC::Heap::jettisonDFGCodeBlock):
* heap/Heap.h:
* jit/JITDriver.h:
(JSC::jitCompileIfAppropriate):
(JSC::jitCompileFunctionIfAppropriate):
* runtime/Executable.cpp:
(JSC::jettisonCodeBlock):
(JSC::EvalExecutable::jitCompile):
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::jitCompile):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::jitCompileForCall):
(JSC::FunctionExecutable::jitCompileForConstruct):
(JSC::FunctionExecutable::produceCodeBlockFor):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
* runtime/Executable.h:
(EvalExecutable):
(FunctionExecutable):
(JSC::FunctionExecutable::codeBlockFor):
* runtime/ExecutionHarness.h:
(JSC::prepareForExecution):
(JSC::prepareFunctionForExecution):
2013-05-09 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should have its own notion of StructureChain, and it should be possible to validate it after compilation finishes
......
......@@ -2029,9 +2029,9 @@
034768DFFF38A50411DB9C8B /* Products */ = {
isa = PBXGroup;
children = (
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
932F5BD90822A1C700736975 /* JavaScriptCore.framework */,
932F5BE10822A1C700736975 /* jsc */,
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */,
141211200A48793C00480255 /* minidom */,
14BD59BF0A3E8F9000BAF59C /* testapi */,
6511230514046A4C002B101D /* testRegExp */,
......
......@@ -314,6 +314,11 @@ public:
{
return !m_value;
}
bool operator==(const MacroAssemblerCodePtr& other) const
{
return m_value == other.m_value;
}
private:
void* m_value;
......
......@@ -1609,7 +1609,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
}
}
CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative)
CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
: m_globalObject(globalObject->vm(), ownerExecutable, globalObject)
, m_heap(&m_globalObject->vm().heap)
, m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters)
......@@ -1627,7 +1627,6 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
, m_sourceOffset(sourceOffset)
, m_firstLineColumnOffset(firstLineColumnOffset)
, m_codeType(unlinkedCodeBlock->codeType())
, m_alternative(alternative)
, m_osrExitCounter(0)
, m_optimizationDelayCounter(0)
, m_reoptimizationRetryCounter(0)
......
......@@ -90,7 +90,7 @@ namespace JSC {
static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
class CodeBlock : public UnconditionalFinalizer, public WeakReferenceHarvester {
class CodeBlock : public RefCounted<CodeBlock>, public UnconditionalFinalizer, public WeakReferenceHarvester {
WTF_MAKE_FAST_ALLOCATED;
friend class JIT;
friend class LLIntOffsetsExtractor;
......@@ -99,7 +99,7 @@ namespace JSC {
protected:
CodeBlock(CopyParsedBlockTag, CodeBlock& other);
CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSGlobalObject*, unsigned baseScopeDepth, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative);
CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSGlobalObject*, unsigned baseScopeDepth, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset);
WriteBarrier<JSGlobalObject> m_globalObject;
Heap* m_heap;
......@@ -123,9 +123,9 @@ namespace JSC {
static ptrdiff_t offsetOfNumParameters() { return OBJECT_OFFSETOF(CodeBlock, m_numParameters); }
CodeBlock* alternative() { return m_alternative.get(); }
PassOwnPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
void setAlternative(PassOwnPtr<CodeBlock> alternative) { m_alternative = alternative; }
PassRefPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
void setAlternative(PassRefPtr<CodeBlock> alternative) { m_alternative = alternative; }
CodeSpecializationKind specializationKind() const
{
return specializationFromIsConstruct(m_isConstructor);
......@@ -1099,8 +1099,8 @@ namespace JSC {
Vector<WriteBarrier<FunctionExecutable> > m_functionDecls;
Vector<WriteBarrier<FunctionExecutable> > m_functionExprs;
OwnPtr<CodeBlock> m_alternative;
RefPtr<CodeBlock> m_alternative;
ExecutionCounter m_llintExecuteCounter;
ExecutionCounter m_jitExecuteCounter;
......@@ -1154,8 +1154,8 @@ namespace JSC {
{
}
GlobalCodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative)
: CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, sourceOffset, firstLineColumnOffset, alternative)
GlobalCodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
: CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, sourceOffset, firstLineColumnOffset)
{
}
};
......@@ -1167,8 +1167,8 @@ namespace JSC {
{
}
ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative)
: GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, 0, firstLineColumnOffset, alternative)
ProgramCodeBlock(ProgramExecutable* ownerExecutable, UnlinkedProgramCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned firstLineColumnOffset)
: GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, 0, firstLineColumnOffset)
{
}
......@@ -1189,8 +1189,8 @@ namespace JSC {
{
}
EvalCodeBlock(EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth, PassOwnPtr<CodeBlock> alternative)
: GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, 0, 1, alternative)
EvalCodeBlock(EvalExecutable* ownerExecutable, UnlinkedEvalCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
: GlobalCodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, baseScopeDepth, sourceProvider, 0, 1)
{
}
......@@ -1217,8 +1217,8 @@ namespace JSC {
{
}
FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative = nullptr)
: CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, sourceOffset, firstLineColumnOffset, alternative)
FunctionCodeBlock(FunctionExecutable* ownerExecutable, UnlinkedFunctionCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset)
: CodeBlock(ownerExecutable, unlinkedCodeBlock, globalObject, 0, sourceProvider, sourceOffset, firstLineColumnOffset)
{
}
......
......@@ -55,6 +55,7 @@ typedef LLVMValueRef LValue;
static inline LType voidType() { return LLVMVoidType(); }
static inline LType int1Type() { return LLVMInt1Type(); }
static inline LType int8Type() { return LLVMInt8Type(); }
static inline LType int32Type() { return LLVMInt32Type(); }
static inline LType int64Type() { return LLVMInt64Type(); }
static inline LType intPtrType() { return LLVMInt64Type(); }
......
......@@ -41,7 +41,8 @@ namespace JSC { namespace FTL {
#define FOR_EACH_ABSTRACT_FIELD(macro) \
macro(JSCell_structure, JSCell::structureOffset()) \
macro(JSObject_butterfly, JSObject::butterflyOffset()) \
macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength())
macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
macro(Structure_typeInfoFlags, Structure::typeInfoFlagsOffset())
#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
macro(variables, sizeof(Register)) \
......
......@@ -33,16 +33,19 @@ namespace JSC { namespace FTL {
CommonValues::CommonValues()
: voidType(FTL::voidType())
, boolean(int1Type())
, int8(int8Type())
, int32(int32Type())
, int64(int64Type())
, intPtr(intPtrType())
, doubleType(FTL::doubleType())
, ref8(pointerType(int8))
, ref32(pointerType(int32))
, ref64(pointerType(int64))
, refPtr(pointerType(intPtr))
, refDouble(pointerType(doubleType))
, booleanTrue(constInt(boolean, true, ZeroExtend))
, booleanFalse(constInt(boolean, false, ZeroExtend))
, int8Zero(constInt(int8, 0, SignExtend))
, int32Zero(constInt(int32, 0, SignExtend))
, int64Zero(constInt(int64, 0, SignExtend))
, intPtrZero(constInt(intPtr, 0, SignExtend))
......
......@@ -45,16 +45,19 @@ public:
const LType voidType;
const LType boolean;
const LType int8;
const LType int32;
const LType int64;
const LType intPtr;
const LType doubleType;
const LType ref8;
const LType ref32;
const LType ref64;
const LType refPtr;
const LType refDouble;
const LValue booleanTrue;
const LValue booleanFalse;
const LValue int8Zero;
const LValue int32Zero;
const LValue int64Zero;
const LValue intPtrZero;
......
......@@ -939,9 +939,12 @@ private:
}
if (m_node->isBinaryUseKind(ObjectUse)) {
masqueradesAsUndefinedWatchpointIfIsStillValid();
m_booleanValues.add(
m_node,
m_out.equal(lowObject(m_node->child1()), lowObject(m_node->child2())));
m_out.equal(
lowNonNullObject(m_node->child1()),
lowNonNullObject(m_node->child2())));
return;
}
......@@ -1092,6 +1095,15 @@ private:
return result;
}
LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
LValue result = lowCell(edge, mode);
speculateNonNullObject(edge, result);
return result;
}
LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
......@@ -1312,6 +1324,22 @@ private:
speculateObject(edge, lowCell(edge));
}
void speculateNonNullObject(Edge edge, LValue cell)
{
LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
FTL_TYPE_CHECK(
jsValueValue(cell), edge, SpecObject,
m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
if (masqueradesAsUndefinedWatchpointIsStillValid())
return;
speculate(
BadType, jsValueValue(cell), edge.node(),
m_out.testNonZero8(
m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
m_out.constInt8(MasqueradesAsUndefined)));
}
void speculateNumber(Edge edge)
{
// Do an early return here because lowDouble() can create a lot of control flow.
......@@ -1332,6 +1360,20 @@ private:
doubleValue(value), edge, SpecRealNumber,
m_out.doubleNotEqualOrUnordered(value, value));
}
bool masqueradesAsUndefinedWatchpointIsStillValid()
{
return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
}
void masqueradesAsUndefinedWatchpointIfIsStillValid()
{
if (!masqueradesAsUndefinedWatchpointIsStillValid())
return;
// FIXME: Implement masquerades-as-undefined watchpoints.
// https://bugs.webkit.org/show_bug.cgi?id=113647
}
bool isLive(Node* node)
{
......
......@@ -105,6 +105,7 @@ public:
LValue param(unsigned index) { return getParam(m_function, index); }
LValue constBool(bool value) { return constInt(boolean, value, ZeroExtend); }
LValue constInt8(int8_t value) { return constInt(int8, value, SignExtend); }
LValue constInt32(int32_t value) { return constInt(int32, value, SignExtend); }
template<typename T>
LValue constIntPtr(T value) { return constInt(intPtr, bitwise_cast<intptr_t>(value), SignExtend); }
......@@ -176,6 +177,7 @@ public:
pointer.heap().decorateInstruction(result, *m_heaps);
}
LValue load8(TypedPointer pointer) { return load(pointer, ref8); }
LValue load32(TypedPointer pointer) { return load(pointer, ref32); }
LValue load64(TypedPointer pointer) { return load(pointer, ref64); }
LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
......@@ -245,6 +247,7 @@ public:
return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
}
LValue load8(LValue base, const AbstractField& field) { return load8(address(base, field)); }
LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); }
LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); }
LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); }
......@@ -276,9 +279,13 @@ public:
LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGT, left, right); }
LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGE, left, right); }
LValue isZero8(LValue value) { return equal(value, int8Zero); }
LValue notZero8(LValue value) { return notEqual(value, int8Zero); }
LValue isZero64(LValue value) { return equal(value, int64Zero); }
LValue notZero64(LValue value) { return notEqual(value, int64Zero); }
LValue testIsZero8(LValue value, LValue mask) { return isZero8(bitAnd(value, mask)); }
LValue testNonZero8(LValue value, LValue mask) { return notZero8(bitAnd(value, mask)); }
LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }
......
......@@ -38,20 +38,18 @@ DFGCodeBlocks::DFGCodeBlocks() { }
DFGCodeBlocks::~DFGCodeBlocks()
{
Vector<CodeBlock*, 16> toRemove;
Vector<RefPtr<CodeBlock>, 16> toRemove;
for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
if ((*iter)->getJITCode()->dfgCommon()->isJettisoned)
toRemove.append(*iter);
toRemove.append(adoptRef(*iter));
}
WTF::deleteAllValues(toRemove);
}
void DFGCodeBlocks::jettison(PassOwnPtr<CodeBlock> codeBlockPtr)
void DFGCodeBlocks::jettison(PassRefPtr<CodeBlock> codeBlockPtr)
{
// We don't want to delete it now; we just want its pointer.
CodeBlock* codeBlock = codeBlockPtr.leakPtr();
CodeBlock* codeBlock = codeBlockPtr.leakRef();
ASSERT(codeBlock);
ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
......@@ -75,14 +73,12 @@ void DFGCodeBlocks::clearMarks()
void DFGCodeBlocks::deleteUnmarkedJettisonedCodeBlocks()
{
Vector<CodeBlock*, 16> toRemove;
Vector<RefPtr<CodeBlock>, 16> toRemove;
for (HashSet<CodeBlock*>::iterator iter = m_set.begin(); iter != m_set.end(); ++iter) {
if ((*iter)->getJITCode()->dfgCommon()->isJettisoned && !(*iter)->getJITCode()->dfgCommon()->mayBeExecuting)
toRemove.append(*iter);
toRemove.append(adoptRef(*iter));
}
WTF::deleteAllValues(toRemove);
}
void DFGCodeBlocks::traceMarkedCodeBlocks(SlotVisitor& visitor)
......
......@@ -59,7 +59,7 @@ public:
// it. This is typically called either from a recompilation trigger, or from
// an unconditional finalizer associated with a CodeBlock that had weak
// references, where some subset of those references were dead.
void jettison(PassOwnPtr<CodeBlock>);
void jettison(PassRefPtr<CodeBlock>);
// Clear all mark bits associated with DFG code blocks.
void clearMarks();
......@@ -86,7 +86,7 @@ class DFGCodeBlocks {
WTF_MAKE_FAST_ALLOCATED;
public:
void jettison(PassOwnPtr<CodeBlock>);
void jettison(PassRefPtr<CodeBlock>);
void clearMarks() { }
void mark(void*) { }
void deleteUnmarkedJettisonedCodeBlocks() { }
......
......@@ -351,7 +351,7 @@ bool Heap::unprotect(JSValue k)
return m_protectedValues.remove(k.asCell());
}
void Heap::jettisonDFGCodeBlock(PassOwnPtr<CodeBlock> codeBlock)
void Heap::jettisonDFGCodeBlock(PassRefPtr<CodeBlock> codeBlock)
{
m_dfgCodeBlocks.jettison(codeBlock);
}
......
......@@ -138,7 +138,7 @@ namespace JSC {
JS_EXPORT_PRIVATE void protect(JSValue);
JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
void jettisonDFGCodeBlock(PassOwnPtr<CodeBlock>);
void jettisonDFGCodeBlock(PassRefPtr<CodeBlock>);
JS_EXPORT_PRIVATE size_t size();
JS_EXPORT_PRIVATE size_t capacity();
......
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -38,7 +38,7 @@
namespace JSC {
template<typename CodeBlockType>
inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& codeBlock, RefPtr<JITCode>& jitCode, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
inline bool jitCompileIfAppropriate(ExecState* exec, CodeBlockType* codeBlock, RefPtr<JITCode>& jitCode, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
{
VM& vm = exec->vm();
......@@ -52,30 +52,27 @@ inline bool jitCompileIfAppropriate(ExecState* exec, OwnPtr<CodeBlockType>& code
RefPtr<JITCode> oldJITCode = jitCode;
bool dfgCompiled = false;
if (JITCode::isOptimizingJIT(jitType))
dfgCompiled = DFG::tryCompile(exec, codeBlock.get(), jitCode, bytecodeIndex);
if (dfgCompiled) {
if (codeBlock->alternative())
if (JITCode::isOptimizingJIT(jitType)) {
if (DFG::tryCompile(exec, codeBlock, jitCode, bytecodeIndex))
codeBlock->alternative()->unlinkIncomingCalls();
} else {
if (codeBlock->alternative()) {
codeBlock = static_pointer_cast<CodeBlockType>(codeBlock->releaseAlternative());
jitCode = oldJITCode;
else {
ASSERT(oldJITCode == jitCode);
return false;
}
jitCode = JIT::compile(&vm, codeBlock.get(), effort);
if (!jitCode) {
jitCode = oldJITCode;
} else {
RefPtr<JITCode> result = JIT::compile(&vm, codeBlock, effort);
if (result)
jitCode = result;
else
return false;
}
}
codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
return true;
}
inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, RefPtr<JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
inline bool jitCompileFunctionIfAppropriate(ExecState* exec, FunctionCodeBlock* codeBlock, RefPtr<JITCode>& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType, unsigned bytecodeIndex, JITCompilationEffort effort)
{
VM& vm = exec->vm();
......@@ -90,26 +87,25 @@ inline bool jitCompileFunctionIfAppropriate(ExecState* exec, OwnPtr<FunctionCode
RefPtr<JITCode> oldJITCode = jitCode;
MacroAssemblerCodePtr oldJITCodeWithArityCheck = jitCodeWithArityCheck;
bool dfgCompiled = false;
if (JITCode::isOptimizingJIT(jitType))
dfgCompiled = DFG::tryCompileFunction(exec, codeBlock.get(), jitCode, jitCodeWithArityCheck, bytecodeIndex);
if (dfgCompiled) {
if (codeBlock->alternative())
if (JITCode::isOptimizingJIT(jitType)) {
if (DFG::tryCompileFunction(exec, codeBlock, jitCode, jitCodeWithArityCheck, bytecodeIndex))
codeBlock->alternative()->unlinkIncomingCalls();
} else {
if (codeBlock->alternative()) {
codeBlock = static_pointer_cast<FunctionCodeBlock>(codeBlock->releaseAlternative());
jitCode = oldJITCode;
jitCodeWithArityCheck = oldJITCodeWithArityCheck;
else {
ASSERT(oldJITCode == jitCode);
ASSERT_UNUSED(oldJITCodeWithArityCheck, oldJITCodeWithArityCheck == jitCodeWithArityCheck);
return false;
}
jitCode = JIT::compile(&vm, codeBlock.get(), effort, &jitCodeWithArityCheck);
if (!jitCode) {
jitCode = oldJITCode;
jitCodeWithArityCheck = oldJITCodeWithArityCheck;
} else {
RefPtr<JITCode> result =
JIT::compile(&vm, codeBlock, effort, &jitCodeWithArityCheck);
if (result)
jitCode = result;
else {
ASSERT_UNUSED(oldJITCodeWithArityCheck, oldJITCodeWithArityCheck == jitCodeWithArityCheck);
return false;
}
}
codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
return true;
......
......@@ -94,11 +94,11 @@ Intrinsic NativeExecutable::intrinsic() const
#if ENABLE(JIT)
// Utility method used for jettisoning code blocks.
template<typename T>
static void jettisonCodeBlock(VM& vm, OwnPtr<T>& codeBlock)
static void jettisonCodeBlock(VM& vm, RefPtr<T>& codeBlock)
{
ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
ASSERT(codeBlock->alternative());
OwnPtr<T> codeBlockToJettison = codeBlock.release();
RefPtr<T> codeBlockToJettison = codeBlock.release();
codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
codeBlockToJettison->unlinkIncomingCalls();
vm.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
......@@ -171,7 +171,7 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsi
#if ENABLE(JIT)
bool EvalExecutable::jitCompile(ExecState* exec)
{
return jitCompileIfAppropriate(exec, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
return jitCompileIfAppropriate(exec, m_evalCodeBlock.get(), m_jitCodeForCall, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
#endif
......@@ -203,10 +203,11 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
VM* vm = &exec->vm();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
RefPtr<EvalCodeBlock> newCodeBlock;
if (!!m_evalCodeBlock) {
PassOwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
m_evalCodeBlock = newCodeBlock;
newCodeBlock = adoptRef(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock));
} else {
UNUSED_PARAM(scope);
UNUSED_PARAM(vm);
......@@ -219,17 +220,18 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
if (!unlinkedEvalCode)
return exception;
OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
m_unlinkedEvalCodeBlock.set(*vm, this, unlinkedEvalCode);
m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
m_evalCodeBlock->copyPostParseDataFromAlternative();