Commit ebe232eb authored by fpizlo@apple.com's avatar fpizlo@apple.com

Getting the instruction stream for a code block should not require two loads

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

Reviewed by Sam Weinig.
        
Introduced the RefCountedArray class, which contains a single inline pointer
to a ref-counted non-resizeable vector backing store. This satisfies the
requirements of CodeBlock, which desires the ability to share instruction
streams with other CodeBlocks. It also reduces the number of loads required
for getting the instruction stream by one.
        
This patch also gets rid of the bytecode discarding logic, since we don't
use it anymore and it's unlikely to ever work right with DFG or LLInt. And
I didn't feel like porting dead code to use RefCountedArray.

* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::instructionOffsetForNth):
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::handlerForBytecodeOffset):
(JSC::CodeBlock::lineNumberForBytecodeOffset):
(JSC::CodeBlock::expressionRangeForBytecodeOffset):
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::numberOfInstructions):
(JSC::CodeBlock::instructions):
(JSC::CodeBlock::instructionCount):
(JSC::CodeBlock::valueProfileForBytecodeOffset):
(JSC):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::Label::setLocation):
(JSC):
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::newLabel):
* bytecompiler/BytecodeGenerator.h:
(JSC):
(BytecodeGenerator):
(JSC::BytecodeGenerator::instructions):
* bytecompiler/Label.h:
(JSC::Label::Label):
(Label):
* dfg/DFGByteCodeCache.h:
(JSC::DFG::ByteCodeCache::~ByteCodeCache):
(JSC::DFG::ByteCodeCache::get):
* jit/JITExceptions.cpp:
(JSC::genericThrow):
* llint/LowLevelInterpreter32_64.asm:
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::codeBlockWithBytecodeFor):
(JSC::FunctionExecutable::produceCodeBlockFor):
* wtf/RefCountedArray.h: Added.
(WTF):
(RefCountedArray):
(WTF::RefCountedArray::RefCountedArray):
(WTF::RefCountedArray::operator=):
(WTF::RefCountedArray::~RefCountedArray):
(WTF::RefCountedArray::size):
(WTF::RefCountedArray::data):
(WTF::RefCountedArray::begin):
(WTF::RefCountedArray::end):
(WTF::RefCountedArray::at):
(WTF::RefCountedArray::operator[]):
(Header):
(WTF::RefCountedArray::Header::size):
(WTF::RefCountedArray::Header::payload):
(WTF::RefCountedArray::Header::fromPayload):
* wtf/Platform.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@108943 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 43a93dc0
2012-02-26 Filip Pizlo <fpizlo@apple.com>
Getting the instruction stream for a code block should not require two loads
https://bugs.webkit.org/show_bug.cgi?id=79608
Reviewed by Sam Weinig.
Introduced the RefCountedArray class, which contains a single inline pointer
to a ref-counted non-resizeable vector backing store. This satisfies the
requirements of CodeBlock, which desires the ability to share instruction
streams with other CodeBlocks. It also reduces the number of loads required
for getting the instruction stream by one.
This patch also gets rid of the bytecode discarding logic, since we don't
use it anymore and it's unlikely to ever work right with DFG or LLInt. And
I didn't feel like porting dead code to use RefCountedArray.
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::instructionOffsetForNth):
(JSC::CodeBlock::dump):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::handlerForBytecodeOffset):
(JSC::CodeBlock::lineNumberForBytecodeOffset):
(JSC::CodeBlock::expressionRangeForBytecodeOffset):
(JSC::CodeBlock::shrinkToFit):
* bytecode/CodeBlock.h:
(CodeBlock):
(JSC::CodeBlock::numberOfInstructions):
(JSC::CodeBlock::instructions):
(JSC::CodeBlock::instructionCount):
(JSC::CodeBlock::valueProfileForBytecodeOffset):
(JSC):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::Label::setLocation):
(JSC):
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::newLabel):
* bytecompiler/BytecodeGenerator.h:
(JSC):
(BytecodeGenerator):
(JSC::BytecodeGenerator::instructions):
* bytecompiler/Label.h:
(JSC::Label::Label):
(Label):
* dfg/DFGByteCodeCache.h:
(JSC::DFG::ByteCodeCache::~ByteCodeCache):
(JSC::DFG::ByteCodeCache::get):
* jit/JITExceptions.cpp:
(JSC::genericThrow):
* llint/LowLevelInterpreter32_64.asm:
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::codeBlockWithBytecodeFor):
(JSC::FunctionExecutable::produceCodeBlockFor):
* wtf/RefCountedArray.h: Added.
(WTF):
(RefCountedArray):
(WTF::RefCountedArray::RefCountedArray):
(WTF::RefCountedArray::operator=):
(WTF::RefCountedArray::~RefCountedArray):
(WTF::RefCountedArray::size):
(WTF::RefCountedArray::data):
(WTF::RefCountedArray::begin):
(WTF::RefCountedArray::end):
(WTF::RefCountedArray::at):
(WTF::RefCountedArray::operator[]):
(Header):
(WTF::RefCountedArray::Header::size):
(WTF::RefCountedArray::Header::payload):
(WTF::RefCountedArray::Header::fromPayload):
* wtf/Platform.h:
2012-02-26 Yusuke Suzuki <utatane.tea@gmail.com>
StringLiteral and NumericLiteral are allowed as ObjectLiteral getter / setter name
......@@ -583,6 +583,7 @@ javascriptcore_sources += \
Source/JavaScriptCore/wtf/ByteArray.h \
Source/JavaScriptCore/wtf/CheckedArithmetic.h \
Source/JavaScriptCore/wtf/CheckedBoolean.h \
Source/JavaScriptCore/wtf/RefCountedArray.h \
Source/JavaScriptCore/wtf/Compiler.h \
Source/JavaScriptCore/wtf/Complex.h \
Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \
......
......@@ -143,6 +143,7 @@
0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; };
0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */; };
0FB5469014FADA7B002C2989 /* RefCountedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */; };
0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -1008,6 +1009,7 @@
0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyOperandValueProfile.cpp; sourceTree = "<group>"; };
0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodOfGettingAValueProfile.h; sourceTree = "<group>"; };
0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodOfGettingAValueProfile.cpp; sourceTree = "<group>"; };
0FB5468E14FADA6F002C2989 /* RefCountedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedArray.h; sourceTree = "<group>"; };
0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; };
0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; };
0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; };
......@@ -2204,6 +2206,7 @@
A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */,
A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */,
C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */,
0FB5468E14FADA6F002C2989 /* RefCountedArray.h */,
BC66BAE213F4928F00C23FAE /* Compiler.h */,
FDA15C1612B03028003A583A /* Complex.h */,
97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */,
......@@ -3401,6 +3404,7 @@
1497209114EB831500FEB1B7 /* PassWeak.h in Headers */,
0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */,
0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */,
0FB5469014FADA7B002C2989 /* RefCountedArray.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -226,7 +226,7 @@ static bool isPropertyAccess(OpcodeID opcodeID)
}
}
static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
{
size_t i = 0;
while (i < instructions.size()) {
......@@ -347,18 +347,13 @@ void CodeBlock::printStructures(const Instruction* vPC) const
void CodeBlock::dump(ExecState* exec) const
{
if (!m_instructions) {
dataLog("No instructions available.\n");
return;
}
size_t instructionCount = 0;
for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
++instructionCount;
dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
static_cast<unsigned long>(instructionCount),
static_cast<unsigned long>(instructions().size()),
static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
this, m_numParameters, m_numCalleeRegisters, m_numVars);
......@@ -1424,11 +1419,9 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
, m_numVars(other.m_numVars)
, m_numCapturedVars(other.m_numCapturedVars)
, m_isConstructor(other.m_isConstructor)
, m_shouldDiscardBytecode(false)
, m_ownerExecutable(*other.m_globalData, other.m_ownerExecutable.get(), other.m_ownerExecutable.get())
, m_globalData(other.m_globalData)
, m_instructions(other.m_instructions)
, m_instructionCount(other.m_instructionCount)
, m_thisRegister(other.m_thisRegister)
, m_argumentsRegister(other.m_argumentsRegister)
, m_activationRegister(other.m_activationRegister)
......@@ -1484,12 +1477,9 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
, m_numCalleeRegisters(0)
, m_numVars(0)
, m_isConstructor(isConstructor)
, m_shouldDiscardBytecode(false)
, m_numParameters(0)
, m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
, m_globalData(0)
, m_instructions(adoptRef(new Instructions))
, m_instructionCount(0)
, m_argumentsRegister(-1)
, m_needsFullScopeChain(ownerExecutable->needsActivation())
, m_usesEval(ownerExecutable->usesEval())
......@@ -1903,12 +1893,6 @@ void CodeBlock::finalizeUnconditionally()
}
}
#endif
// Handle the bytecode discarding chore.
if (m_shouldDiscardBytecode) {
discardBytecode();
m_shouldDiscardBytecode = false;
}
}
void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor)
......@@ -1980,7 +1964,7 @@ void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor)
HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
{
ASSERT(bytecodeOffset < m_instructionCount);
ASSERT(bytecodeOffset < instructions().size());
if (!m_rareData)
return 0;
......@@ -1998,7 +1982,7 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
{
ASSERT(bytecodeOffset < m_instructionCount);
ASSERT(bytecodeOffset < instructions().size());
if (!m_rareData)
return m_ownerExecutable->source().firstLine();
......@@ -2022,7 +2006,7 @@ int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
{
ASSERT(bytecodeOffset < m_instructionCount);
ASSERT(bytecodeOffset < instructions().size());
if (!m_rareData) {
startOffset = 0;
......@@ -2102,8 +2086,6 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
void CodeBlock::shrinkToFit()
{
instructions().shrinkToFit();
#if ENABLE(CLASSIC_INTERPRETER)
m_propertyAccessInstructions.shrinkToFit();
m_globalResolveInstructions.shrinkToFit();
......
......@@ -61,6 +61,7 @@
#include "UString.h"
#include "UnconditionalFinalizer.h"
#include "ValueProfile.h"
#include <wtf/RefCountedArray.h>
#include <wtf/FastAllocBase.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
......@@ -127,8 +128,6 @@ namespace JSC {
}
#endif
bool canProduceCopyWithBytecode() { return hasInstructions(); }
void visitAggregate(SlotVisitor&);
static void dumpStatistics();
......@@ -341,20 +340,13 @@ namespace JSC {
void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
bool hasInstructions() const { return !!m_instructions; }
unsigned numberOfInstructions() const { return !m_instructions ? 0 : m_instructions->m_instructions.size(); }
Vector<Instruction>& instructions() { return m_instructions->m_instructions; }
const Vector<Instruction>& instructions() const { return m_instructions->m_instructions; }
void discardBytecode() { m_instructions.clear(); }
void discardBytecodeLater()
{
m_shouldDiscardBytecode = true;
}
unsigned numberOfInstructions() const { return m_instructions.size(); }
RefCountedArray<Instruction>& instructions() { return m_instructions; }
const RefCountedArray<Instruction>& instructions() const { return m_instructions; }
bool usesOpcode(OpcodeID);
unsigned instructionCount() { return m_instructionCount; }
void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
unsigned instructionCount() { return m_instructions.size(); }
#if ENABLE(JIT)
void setJITCode(const JITCode& code, MacroAssemblerCodePtr codeWithArityCheck)
......@@ -541,11 +533,10 @@ namespace JSC {
{
ValueProfile* result = WTF::genericBinarySearch<ValueProfile, int, getValueProfileBytecodeOffset>(m_valueProfiles, m_valueProfiles.size(), bytecodeOffset);
ASSERT(result->m_bytecodeOffset != -1);
ASSERT(!hasInstructions()
|| instructions()[bytecodeOffset + opcodeLength(
m_globalData->interpreter->getOpcodeID(
instructions()[
bytecodeOffset].u.opcode)) - 1].u.profile == result);
ASSERT(instructions()[bytecodeOffset + opcodeLength(
m_globalData->interpreter->getOpcodeID(
instructions()[
bytecodeOffset].u.opcode)) - 1].u.profile == result);
return result;
}
PredictedType valueProfilePredictionForBytecodeOffset(int bytecodeOffset)
......@@ -1047,9 +1038,6 @@ namespace JSC {
int m_numCapturedVars;
bool m_isConstructor;
// This is public because otherwise we would have many friends.
bool m_shouldDiscardBytecode;
protected:
#if ENABLE(JIT)
virtual void jitCompileImpl(JSGlobalData&) = 0;
......@@ -1115,11 +1103,7 @@ namespace JSC {
WriteBarrier<ScriptExecutable> m_ownerExecutable;
JSGlobalData* m_globalData;
struct Instructions : public RefCounted<Instructions> {
Vector<Instruction> m_instructions;
};
RefPtr<Instructions> m_instructions;
unsigned m_instructionCount;
RefCountedArray<Instruction> m_instructions;
int m_thisRegister;
int m_argumentsRegister;
......@@ -1379,27 +1363,6 @@ namespace JSC {
#endif
};
// Use this if you want to copy a code block and you're paranoid about a GC
// happening.
class BytecodeDestructionBlocker {
public:
BytecodeDestructionBlocker(CodeBlock* codeBlock)
: m_codeBlock(codeBlock)
, m_oldValueOfShouldDiscardBytecode(codeBlock->m_shouldDiscardBytecode)
{
codeBlock->m_shouldDiscardBytecode = false;
}
~BytecodeDestructionBlocker()
{
m_codeBlock->m_shouldDiscardBytecode = m_oldValueOfShouldDiscardBytecode;
}
private:
CodeBlock* m_codeBlock;
bool m_oldValueOfShouldDiscardBytecode;
};
inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock)
{
if (codeOrigin.inlineCallFrame) {
......
......@@ -119,6 +119,15 @@ namespace JSC {
expected by the callee.
*/
void Label::setLocation(unsigned location)
{
m_location = location;
unsigned size = m_unresolvedJumps.size();
for (unsigned i = 0; i < size; ++i)
m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
}
#ifndef NDEBUG
void ResolveResult::checkValidity()
{
......@@ -171,8 +180,8 @@ JSObject* BytecodeGenerator::generate()
m_codeBlock->setThisRegister(m_thisRegister.index());
m_scopeNode->emitBytecode(*this);
m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
m_codeBlock->instructions() = RefCountedArray<Instruction>(m_instructions);
if (s_dumpsGeneratedCode)
m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
......@@ -607,7 +616,7 @@ PassRefPtr<Label> BytecodeGenerator::newLabel()
m_labels.removeLast();
// Allocate new label ID.
m_labels.append(m_codeBlock);
m_labels.append(this);
return &m_labels.last();
}
......
......@@ -48,6 +48,7 @@
namespace JSC {
class Identifier;
class Label;
class ScopeChainNode;
class CallArguments {
......@@ -532,6 +533,8 @@ namespace JSC {
ScopeChainNode* scopeChain() const { return m_scopeChain.get(); }
private:
friend class Label;
void emitOpcode(OpcodeID);
ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
......@@ -611,7 +614,7 @@ namespace JSC {
RegisterID* emitInitLazyRegister(RegisterID*);
Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
Vector<Instruction>& instructions() { return m_instructions; }
SymbolTable& symbolTable() { return *m_symbolTable; }
bool shouldOptimizeLocals()
......@@ -644,6 +647,8 @@ namespace JSC {
void createArgumentsIfNecessary();
void createActivationIfNecessary();
RegisterID* createLazyRegisterIfNecessary(RegisterID*);
Vector<Instruction> m_instructions;
bool m_shouldEmitDebugHooks;
bool m_shouldEmitProfileHooks;
......
......@@ -39,21 +39,14 @@ namespace JSC {
class Label {
public:
explicit Label(CodeBlock* codeBlock)
explicit Label(BytecodeGenerator* generator)
: m_refCount(0)
, m_location(invalidLocation)
, m_codeBlock(codeBlock)
, m_generator(generator)
{
}
void setLocation(unsigned location)
{
m_location = location;
unsigned size = m_unresolvedJumps.size();
for (unsigned i = 0; i < size; ++i)
m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
}
void setLocation(unsigned);
int bind(int opcode, int offset) const
{
......@@ -81,7 +74,7 @@ namespace JSC {
int m_refCount;
unsigned m_location;
CodeBlock* m_codeBlock;
BytecodeGenerator* m_generator;
mutable JumpVector m_unresolvedJumps;
};
......
......@@ -138,7 +138,6 @@ public:
delete iter->second.codeBlock;
continue;
}
iter->second.codeBlock->m_shouldDiscardBytecode = iter->second.oldValueOfShouldDiscardBytecode;
}
}
......@@ -155,7 +154,6 @@ public:
value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind());
if (value.codeBlock) {
value.owned = false;
value.oldValueOfShouldDiscardBytecode = value.codeBlock->m_shouldDiscardBytecode;
} else {
// Nope, so try to parse one.
JSObject* exception;
......@@ -171,13 +169,6 @@ public:
value.codeBlock = 0;
}
// If we're about to return a code block, make sure that we're not going
// to be discarding its bytecode if a GC were to happen during DFG
// compilation. That's unlikely, but it's good to thoroughly enjoy this
// kind of paranoia.
if (!!value.codeBlock)
value.codeBlock->m_shouldDiscardBytecode = false;
m_map.add(key, value);
return value.codeBlock;
......
......@@ -48,8 +48,7 @@ ExceptionHandler genericThrow(JSGlobalData* globalData, ExecState* callFrame, JS
Instruction* catchPCForInterpreter = 0;
if (handler) {
catchRoutine = handler->nativeCode.executableAddress();
if (callFrame->codeBlock()->hasInstructions())
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target];
} else
catchRoutine = FunctionPtr(ctiOpThrowNotCaught).value();
......
......@@ -443,8 +443,7 @@ macro prologue(codeBlockGetter, codeBlockSetter, osrSlowPath, traceSlowPath)
codeBlockSetter(t1)
# Set up the PC.
loadp CodeBlock::m_instructions[t1], t0
loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
loadp CodeBlock::m_instructions[t1], PC
end
# Expects that CodeBlock is in t1, which is what prologue() leaves behind.
......@@ -503,8 +502,7 @@ macro functionArityCheck(doneLabel, slow_path)
.continue:
# Reload CodeBlock and PC, since the slow_path clobbered it.
loadp CodeBlock[cfr], t1
loadp CodeBlock::m_instructions[t1], t0
loadp CodeBlock::Instructions::m_instructions + VectorBufferOffset[t0], PC
loadp CodeBlock::m_instructions[t1], PC
jmp doneLabel
end
......
......@@ -210,8 +210,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
if (!!m_evalCodeBlock && m_evalCodeBlock->canProduceCopyWithBytecode()) {
BytecodeDestructionBlocker blocker(m_evalCodeBlock.get());
if (!!m_evalCodeBlock) {
OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
m_evalCodeBlock = newCodeBlock.release();
......@@ -346,8 +345,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
if (!!m_programCodeBlock && m_programCodeBlock->canProduceCopyWithBytecode()) {
BytecodeDestructionBlocker blocker(m_programCodeBlock.get());
if (!!m_programCodeBlock) {
OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
m_programCodeBlock = newCodeBlock.release();
......@@ -494,18 +492,13 @@ void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
{
FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);
if (codeBlock->canProduceCopyWithBytecode())
return codeBlock;
return 0;
return baselineCodeBlockFor(kind);
}
PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
{
if (!!codeBlockFor(specializationKind) && codeBlockFor(specializationKind)->canProduceCopyWithBytecode()) {
BytecodeDestructionBlocker blocker(codeBlockFor(specializationKind).get());
if (!!codeBlockFor(specializationKind))
return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
}
exception = 0;
JSGlobalData* globalData = scopeChainNode->globalData;
......
......@@ -920,7 +920,7 @@
#define ENABLE_JIT 0
#endif
/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
/* The JIT is enabled by default on all x86, x86-64, ARM & MIPS platforms. */
#if !defined(ENABLE_JIT) \
&& (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \
&& (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \
......
/*
* Copyright (C) 2011 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.
*/
#ifndef RefCountedArray_h
#define RefCountedArray_h
#include <wtf/FastMalloc.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
// This implements a reference counted array for POD** values, which is optimized for:
// - An empty array only uses one word.
// - A copy of the array only uses one word (i.e. assignment means aliasing).
// - The vector can't grow beyond 2^32-1 elements.
// - In all other regards this has similar space usage to a Vector.
//
// ** This could be modified to support non-POD values quite easily. It just
// hasn't been, so far, because there has been no need. Moreover, even now,
// it's used for things that aren't quite POD according to the official
// defintion, such as JSC::Instruction.
namespace WTF {
template<typename T>
class RefCountedArray {
public:
RefCountedArray()
: m_data(0)
{
}
RefCountedArray(const RefCountedArray& other)
: m_data(other.m_data)
{
if (m_data)
Header::fromPayload(m_data)->refCount++;
}
explicit RefCountedArray(const Vector<T>& other)
{
if (other.isEmpty()) {
m_data = 0;
return;
}
m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * other.size())))->payload();
Header::fromPayload(m_data)->refCount = 1;
Header::fromPayload(m_data)->length = other.size();
ASSERT(Header::fromPayload(m_data)->length == other.size());
memcpy(m_data, other.begin(), sizeof(T) * other.size());
}
RefCountedArray& operator=(const RefCountedArray& other)
{
T* oldData = m_data;