Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (162824 => 162825)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2014-01-27 05:45:30 UTC (rev 162825)
@@ -84,6 +84,7 @@
bytecode/StructureStubClearingWatchpoint.cpp
bytecode/StructureStubInfo.cpp
bytecode/UnlinkedCodeBlock.cpp
+ bytecode/UnlinkedInstructionStream.cpp
bytecode/ValueRecovery.cpp
bytecode/Watchpoint.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (162824 => 162825)
--- trunk/Source/_javascript_Core/ChangeLog 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-01-27 05:45:30 UTC (rev 162825)
@@ -1,3 +1,53 @@
+2014-01-26 Andreas Kling <[email protected]>
+
+ JSC: Pack unlinked instructions harder.
+ <https://webkit.org/b/127660>
+
+ Store UnlinkedCodeBlock's instructions in a variable-length stream
+ to reduce memory usage. Compression rate ends up around 60-61%.
+
+ The format is very simple. Every instruction starts with a 1 byte
+ opcode. It's followed by an opcode-dependent number of argument
+ values, each encoded separately for maximum packing. There are
+ 7 packed value formats:
+
+ 5-bit positive integer
+ 5-bit negative integer
+ 13-bit positive integer
+ 13-bit positive integer
+ 5-bit constant register index
+ 13-bit constant register index
+ 32-bit value (fallback)
+
+ 27.5 MB progression on Membuster3. (~2% of total memory.)
+
+ Reviewed by Filip Pizlo.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/UnlinkedInstructionStream.h: Added.
+ (JSC::UnlinkedInstructionStream::count):
+ (JSC::UnlinkedInstructionStream::Reader::atEnd):
+ * bytecode/UnlinkedInstructionStream.cpp: Added.
+ (JSC::UnlinkedInstructionStream::Reader::Reader):
+ (JSC::UnlinkedInstructionStream::Reader::read8):
+ (JSC::UnlinkedInstructionStream::Reader::read32):
+ (JSC::UnlinkedInstructionStream::Reader::next):
+ (JSC::append8):
+ (JSC::append32):
+ (JSC::UnlinkedInstructionStream::UnlinkedInstructionStream):
+ (JSC::UnlinkedInstructionStream::unpackForDebugging):
+ * bytecompiler/BytecodeGenerator.cpp:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock):
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::UnlinkedCodeBlock::lineNumberForBytecodeOffset):
+ (JSC::dumpLineColumnEntry):
+ (JSC::UnlinkedCodeBlock::expressionRangeForBytecodeOffset):
+ (JSC::UnlinkedCodeBlock::setInstructions):
+ (JSC::UnlinkedCodeBlock::instructions):
+ * bytecode/UnlinkedCodeBlock.h:
+ (JSC::BytecodeGenerator::generate):
+
2014-01-26 Joseph Pecoraro <[email protected]>
Web Inspector: Move InspectorDebuggerAgent into _javascript_Core
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (162824 => 162825)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2014-01-27 05:45:30 UTC (rev 162825)
@@ -184,6 +184,8 @@
Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.h \
Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp \
Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h \
+ Source/_javascript_Core/bytecode/UnlinkedInstructionStream.cpp \
+ Source/_javascript_Core/bytecode/UnlinkedInstructionStream.h \
Source/_javascript_Core/bytecode/ValueProfile.h \
Source/_javascript_Core/bytecode/ValueRecovery.cpp \
Source/_javascript_Core/bytecode/ValueRecovery.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (162824 => 162825)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2014-01-27 05:45:30 UTC (rev 162825)
@@ -341,6 +341,7 @@
<ClCompile Include="..\bytecode\StructureStubClearingWatchpoint.cpp" />
<ClCompile Include="..\bytecode\StructureStubInfo.cpp" />
<ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp" />
+ <ClCompile Include="..\bytecode\UnlinkedInstructionStream.cpp" />
<ClCompile Include="..\bytecode\ValueRecovery.cpp" />
<ClCompile Include="..\bytecode\Watchpoint.cpp" />
<ClCompile Include="..\bytecompiler\BytecodeGenerator.cpp" />
@@ -841,6 +842,7 @@
<ClInclude Include="..\bytecode\StructureStubClearingWatchpoint.h" />
<ClInclude Include="..\bytecode\StructureStubInfo.h" />
<ClInclude Include="..\bytecode\UnlinkedCodeBlock.h" />
+ <ClInclude Include="..\bytecode\UnlinkedInstructionStream.h" />
<ClInclude Include="..\bytecode\ValueProfile.h" />
<ClInclude Include="..\bytecode\ValueRecovery.h" />
<ClInclude Include="..\bytecode\VariableWatchpointSet.h" />
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (162824 => 162825)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2014-01-27 05:45:30 UTC (rev 162825)
@@ -186,6 +186,9 @@
<ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp">
<Filter>bytecode</Filter>
</ClCompile>
+ <ClCompile Include="..\bytecode\UnlinkedInstructionStream.cpp">
+ <Filter>bytecode</Filter>
+ </ClCompile>
<ClCompile Include="..\bytecode\Watchpoint.cpp">
<Filter>bytecode</Filter>
</ClCompile>
@@ -1559,6 +1562,9 @@
<ClInclude Include="..\bytecode\UnlinkedCodeBlock.h">
<Filter>bytecode</Filter>
</ClInclude>
+ <ClInclude Include="..\bytecode\UnlinkedInstructionStream.h">
+ <Filter>bytecode</Filter>
+ </ClInclude>
<ClInclude Include="..\bytecode\ValueProfile.h">
<Filter>bytecode</Filter>
</ClInclude>
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (162824 => 162825)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-01-27 05:45:30 UTC (rev 162825)
@@ -1170,6 +1170,7 @@
A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FCC26C17A0B6AA00786D1A /* FTLSwitchCase.h */; settings = {ATTRIBUTES = (Private, ); }; };
A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; };
ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };
+ B59F89391891F29F00D5CCDC /* UnlinkedInstructionStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */; };
BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */; };
@@ -2591,6 +2592,8 @@
A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyTable.cpp; sourceTree = "<group>"; };
+ B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedInstructionStream.h; sourceTree = "<group>"; };
+ B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedInstructionStream.cpp; sourceTree = "<group>"; };
BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ToolExecutable.xcconfig; sourceTree = "<group>"; };
BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorConstructor.cpp; sourceTree = "<group>"; };
BC02E9050E1839DB000F9297 /* ErrorConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorConstructor.h; sourceTree = "<group>"; };
@@ -4366,6 +4369,8 @@
BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */,
A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */,
A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */,
+ B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */,
+ B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */,
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */,
0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */,
0F426A451460CBAB00131F8F /* ValueRecovery.h */,
@@ -5965,6 +5970,7 @@
86E3C616167BABEE006D760A /* JSContext.mm in Sources */,
14BD5A300A3E91F600BAF59C /* JSContextRef.cpp in Sources */,
A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */,
+ B59F89391891F29F00D5CCDC /* UnlinkedInstructionStream.cpp in Sources */,
0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */,
0F2B66ED17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp in Sources */,
978801401471AD920041B016 /* JSDateMath.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (162824 => 162825)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2014-01-27 05:45:30 UTC (rev 162825)
@@ -54,6 +54,7 @@
#include "Repatch.h"
#include "RepatchBuffer.h"
#include "SlotVisitorInlines.h"
+#include "UnlinkedInstructionStream.h"
#include <wtf/BagToHashMap.h>
#include <wtf/CommaPrinter.h>
#include <wtf/StringExtras.h>
@@ -1658,21 +1659,25 @@
m_objectAllocationProfiles.resizeToFit(size);
// Copy and translate the UnlinkedInstructions
- size_t instructionCount = unlinkedCodeBlock->instructions().size();
- UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data();
+ unsigned instructionCount = unlinkedCodeBlock->instructions().count();
+ UnlinkedInstructionStream::Reader instructionReader(unlinkedCodeBlock->instructions());
+
Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount);
- for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) {
- unsigned opLength = opcodeLength(pc[i].u.opcode);
- instructions[i] = vm()->interpreter->getOpcode(pc[i].u.opcode);
+ for (unsigned i = 0; !instructionReader.atEnd(); ) {
+ const UnlinkedInstruction* pc = instructionReader.next();
+
+ unsigned opLength = opcodeLength(pc[0].u.opcode);
+
+ instructions[i] = vm()->interpreter->getOpcode(pc[0].u.opcode);
for (size_t j = 1; j < opLength; ++j) {
if (sizeof(int32_t) != sizeof(intptr_t))
instructions[i + j].u.pointer = 0;
- instructions[i + j].u.operand = pc[i + j].u.operand;
+ instructions[i + j].u.operand = pc[j].u.operand;
}
- switch (pc[i].u.opcode) {
+ switch (pc[0].u.opcode) {
case op_get_by_val:
case op_get_argument_by_val: {
- int arrayProfileIndex = pc[i + opLength - 2].u.operand;
+ int arrayProfileIndex = pc[opLength - 2].u.operand;
m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
@@ -1680,20 +1685,20 @@
}
case op_get_by_id:
case op_call_varargs: {
- ValueProfile* profile = "" + opLength - 1].u.operand];
+ ValueProfile* profile = "" - 1].u.operand];
ASSERT(profile->m_bytecodeOffset == -1);
profile->m_bytecodeOffset = i;
instructions[i + opLength - 1] = profile;
break;
}
case op_put_by_val: {
- int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+ int arrayProfileIndex = pc[opLength - 1].u.operand;
m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
break;
}
case op_put_by_val_direct: {
- int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+ int arrayProfileIndex = pc[opLength - 1].u.operand;
m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
break;
@@ -1702,14 +1707,14 @@
case op_new_array:
case op_new_array_buffer:
case op_new_array_with_size: {
- int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand;
+ int arrayAllocationProfileIndex = pc[opLength - 1].u.operand;
instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
break;
}
case op_new_object: {
- int objectAllocationProfileIndex = pc[i + opLength - 1].u.operand;
+ int objectAllocationProfileIndex = pc[opLength - 1].u.operand;
ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
- int inferredInlineCapacity = pc[i + opLength - 2].u.operand;
+ int inferredInlineCapacity = pc[opLength - 2].u.operand;
instructions[i + opLength - 1] = objectAllocationProfile;
objectAllocationProfile->initialize(*vm(),
@@ -1719,23 +1724,23 @@
case op_call:
case op_call_eval: {
- ValueProfile* profile = "" + opLength - 1].u.operand];
+ ValueProfile* profile = "" - 1].u.operand];
ASSERT(profile->m_bytecodeOffset == -1);
profile->m_bytecodeOffset = i;
instructions[i + opLength - 1] = profile;
- int arrayProfileIndex = pc[i + opLength - 2].u.operand;
+ int arrayProfileIndex = pc[opLength - 2].u.operand;
m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
#if ENABLE(LLINT)
- instructions[i + 5] = &m_llintCallLinkInfos[pc[i + 5].u.operand];
+ instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
#endif
break;
}
case op_construct: {
#if ENABLE(LLINT)
- instructions[i + 5] = &m_llintCallLinkInfos[pc[i + 5].u.operand];
+ instructions[i + 5] = &m_llintCallLinkInfos[pc[5].u.operand];
#endif
- ValueProfile* profile = "" + opLength - 1].u.operand];
+ ValueProfile* profile = "" - 1].u.operand];
ASSERT(profile->m_bytecodeOffset == -1);
profile->m_bytecodeOffset = i;
instructions[i + opLength - 1] = profile;
@@ -1758,7 +1763,7 @@
case op_init_global_const_nop: {
ASSERT(codeType() == GlobalCode);
- Identifier ident = identifier(pc[i + 4].u.operand);
+ Identifier ident = identifier(pc[4].u.operand);
SymbolTableEntry entry = m_globalObject->symbolTable()->get(ident.impl());
if (entry.isNull())
break;
@@ -1769,8 +1774,8 @@
}
case op_resolve_scope: {
- const Identifier& ident = identifier(pc[i + 2].u.operand);
- ResolveType type = static_cast<ResolveType>(pc[i + 3].u.operand);
+ const Identifier& ident = identifier(pc[2].u.operand);
+ ResolveType type = static_cast<ResolveType>(pc[3].u.operand);
ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Get, type);
instructions[i + 3].u.operand = op.type;
@@ -1781,14 +1786,14 @@
}
case op_get_from_scope: {
- ValueProfile* profile = "" + opLength - 1].u.operand];
+ ValueProfile* profile = "" - 1].u.operand];
ASSERT(profile->m_bytecodeOffset == -1);
profile->m_bytecodeOffset = i;
instructions[i + opLength - 1] = profile;
// get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
- const Identifier& ident = identifier(pc[i + 3].u.operand);
- ResolveModeAndType modeAndType = ResolveModeAndType(pc[i + 4].u.operand);
+ const Identifier& ident = identifier(pc[3].u.operand);
+ ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Get, modeAndType.type());
instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand();
@@ -1802,8 +1807,8 @@
case op_put_to_scope: {
// put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
- const Identifier& ident = identifier(pc[i + 2].u.operand);
- ResolveModeAndType modeAndType = ResolveModeAndType(pc[i + 4].u.operand);
+ const Identifier& ident = identifier(pc[2].u.operand);
+ ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Put, modeAndType.type());
instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand();
@@ -1820,11 +1825,11 @@
case op_captured_mov:
case op_new_captured_func: {
- if (pc[i + 3].u.index == UINT_MAX) {
+ if (pc[3].u.index == UINT_MAX) {
instructions[i + 3].u.watchpointSet = 0;
break;
}
- StringImpl* uid = identifier(pc[i + 3].u.index).impl();
+ StringImpl* uid = identifier(pc[3].u.index).impl();
RELEASE_ASSERT(didCloneSymbolTable);
ConcurrentJITLocker locker(m_symbolTable->m_lock);
SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid);
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (162824 => 162825)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2014-01-27 05:45:30 UTC (rev 162825)
@@ -37,6 +37,7 @@
#include "SourceProvider.h"
#include "Structure.h"
#include "SymbolTable.h"
+#include "UnlinkedInstructionStream.h"
#include <wtf/DataLog.h>
namespace JSC {
@@ -247,7 +248,7 @@
int UnlinkedCodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
{
- ASSERT(bytecodeOffset < instructions().size());
+ ASSERT(bytecodeOffset < instructions().count());
int divot;
int startOffset;
int endOffset;
@@ -278,8 +279,9 @@
}
#ifndef NDEBUG
-static void dumpLineColumnEntry(size_t index, const RefCountedArray<UnlinkedInstruction>& instructions, unsigned instructionOffset, unsigned line, unsigned column)
+static void dumpLineColumnEntry(size_t index, const UnlinkedInstructionStream& instructionStream, unsigned instructionOffset, unsigned line, unsigned column)
{
+ const auto& instructions = instructionStream.unpackForDebugging();
OpcodeID opcode = instructions[instructionOffset].u.opcode;
const char* event = "";
if (opcode == op_debug) {
@@ -315,7 +317,7 @@
void UnlinkedCodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset,
int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column)
{
- ASSERT(bytecodeOffset < instructions().size());
+ ASSERT(bytecodeOffset < instructions().count());
if (!m_expressionInfo.size()) {
startOffset = 0;
@@ -437,5 +439,16 @@
jsCast<UnlinkedFunctionExecutable*>(cell)->~UnlinkedFunctionExecutable();
}
+void UnlinkedCodeBlock::setInstructions(std::unique_ptr<UnlinkedInstructionStream> instructions)
+{
+ m_unlinkedInstructions = std::move(instructions);
}
+const UnlinkedInstructionStream& UnlinkedCodeBlock::instructions() const
+{
+ ASSERT(m_unlinkedInstructions.get());
+ return *m_unlinkedInstructions;
+}
+
+}
+
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (162824 => 162825)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2014-01-27 05:45:30 UTC (rev 162825)
@@ -57,6 +57,7 @@
class SymbolTable;
class UnlinkedCodeBlock;
class UnlinkedFunctionCodeBlock;
+class UnlinkedInstructionStream;
typedef unsigned UnlinkedValueProfile;
typedef unsigned UnlinkedArrayProfile;
@@ -341,9 +342,8 @@
}
}
- unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
- RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
- const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
+ void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
+ const UnlinkedInstructionStream& instructions() const;
int m_numVars;
int m_numCapturedVars;
@@ -484,7 +484,7 @@
void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
- RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
+ std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
int m_numParameters;
VM* m_vm;
Added: trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.cpp (0 => 162825)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.cpp (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.cpp 2014-01-27 05:45:30 UTC (rev 162825)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "config.h"
+#include "UnlinkedInstructionStream.h"
+
+namespace JSC {
+
+// Unlinked instructions are packed in a simple stream format.
+//
+// The first byte is always the opcode.
+// It's followed by an opcode-dependent number of argument values.
+// The first 3 bits of each value determines the format:
+//
+// 5-bit positive integer (1 byte total)
+// 5-bit negative integer (1 byte total)
+// 13-bit positive integer (2 bytes total)
+// 13-bit negative integer (2 bytes total)
+// 5-bit constant register index, based at 0x40000000 (1 byte total)
+// 13-bit constant register index, based at 0x40000000 (2 bytes total)
+// 32-bit raw value (5 bytes total)
+
+enum PackedValueType {
+ Positive5Bit = 0,
+ Negative5Bit,
+ Positive13Bit,
+ Negative13Bit,
+ ConstantRegister5Bit,
+ ConstantRegister13Bit,
+ Full32Bit
+};
+
+UnlinkedInstructionStream::Reader::Reader(const UnlinkedInstructionStream& stream)
+ : m_stream(stream)
+ , m_index(0)
+{
+}
+
+inline unsigned char UnlinkedInstructionStream::Reader::read8()
+{
+ return m_stream.m_data.data()[m_index++];
+}
+
+inline unsigned UnlinkedInstructionStream::Reader::read32()
+{
+ const unsigned char* data = ""
+ unsigned char type = data[0] >> 5;
+
+ switch (type) {
+ case Positive5Bit:
+ m_index++;
+ return data[0];
+ case Negative5Bit:
+ m_index++;
+ return 0xffffffe0 | data[0];
+ case Positive13Bit:
+ m_index += 2;
+ return ((data[0] & 0x1F) << 8) | data[1];
+ case Negative13Bit:
+ m_index += 2;
+ return 0xffffe000 | ((data[0] & 0x1F) << 8) | data[1];
+ case ConstantRegister5Bit:
+ m_index++;
+ return 0x40000000 | (data[0] & 0x1F);
+ case ConstantRegister13Bit:
+ m_index += 2;
+ return 0x40000000 | ((data[0] & 0x1F) << 8) | data[1];
+ default:
+ ASSERT(type == Full32Bit);
+ m_index += 5;
+ return data[1] | data[2] << 8 | data[3] << 16 | data[4] << 24;
+ }
+}
+
+const UnlinkedInstruction* UnlinkedInstructionStream::Reader::next()
+{
+ m_unpackedBuffer[0].u.opcode = static_cast<OpcodeID>(read8());
+ unsigned opLength = opcodeLength(m_unpackedBuffer[0].u.opcode);
+ for (unsigned i = 1; i < opLength; ++i)
+ m_unpackedBuffer[i].u.index = read32();
+ return m_unpackedBuffer;
+}
+
+static void append8(unsigned char*& ptr, unsigned char value)
+{
+ *(ptr++) = value;
+}
+
+static void append32(unsigned char*& ptr, unsigned value)
+{
+ if (!(value & 0xffffffe0)) {
+ *(ptr++) = value;
+ return;
+ }
+
+ if ((value & 0xffffffe0) == 0xffffffe0) {
+ *(ptr++) = (Negative5Bit << 5) | (value & 0x1f);
+ return;
+ }
+
+ if ((value & 0xffffffe0) == 0x40000000) {
+ *(ptr++) = (ConstantRegister5Bit << 5) | (value & 0x1f);
+ return;
+ }
+
+ if (!(value & 0xffffe000)) {
+ *(ptr++) = (Positive13Bit << 5) | ((value >> 8) & 0x1f);
+ *(ptr++) = value & 0xff;
+ return;
+ }
+
+ if ((value & 0xffffe000) == 0xffffe000) {
+ *(ptr++) = (Negative13Bit << 5) | ((value >> 8) & 0x1f);
+ *(ptr++) = value & 0xff;
+ return;
+ }
+
+ if ((value & 0xffffe000) == 0x40000000) {
+ *(ptr++) = (ConstantRegister13Bit << 5) | ((value >> 8) & 0x1f);
+ *(ptr++) = value & 0xff;
+ return;
+ }
+
+ *(ptr++) = Full32Bit << 5;
+ *(ptr++) = value & 0xff;
+ *(ptr++) = (value >> 8) & 0xff;
+ *(ptr++) = (value >> 16) & 0xff;
+ *(ptr++) = (value >> 24) & 0xff;
+}
+
+UnlinkedInstructionStream::UnlinkedInstructionStream(const Vector<UnlinkedInstruction>& instructions)
+ : m_instructionCount(instructions.size())
+{
+ Vector<unsigned char> buffer;
+
+ // Reserve enough space up front so we never have to reallocate when appending.
+ buffer.resizeToFit(m_instructionCount * 5);
+ unsigned char* ptr = buffer.data();
+
+ const UnlinkedInstruction* instructionsData = instructions.data();
+ for (unsigned i = 0; i < m_instructionCount;) {
+ const UnlinkedInstruction* pc = &instructionsData[i];
+ OpcodeID opcode = pc[0].u.opcode;
+ append8(ptr, opcode);
+
+ unsigned opLength = opcodeLength(opcode);
+
+ for (unsigned j = 1; j < opLength; ++j)
+ append32(ptr, pc[j].u.index);
+
+ i += opLength;
+ }
+
+ buffer.shrink(ptr - buffer.data());
+ m_data = RefCountedArray<unsigned char>(buffer);
+}
+
+#ifndef NDEBUG
+const RefCountedArray<UnlinkedInstruction>& UnlinkedInstructionStream::unpackForDebugging() const
+{
+ if (!m_unpackedInstructionsForDebugging.size()) {
+ m_unpackedInstructionsForDebugging = RefCountedArray<UnlinkedInstruction>(m_instructionCount);
+
+ Reader instructionReader(*this);
+ for (unsigned i = 0; !instructionReader.atEnd(); ) {
+ const UnlinkedInstruction* pc = instructionReader.next();
+ unsigned opLength = opcodeLength(pc[0].u.opcode);
+ for (unsigned j = 0; j < opLength; ++j)
+ m_unpackedInstructionsForDebugging[i++] = pc[j];
+ }
+ }
+
+ return m_unpackedInstructionsForDebugging;
+}
+#endif
+
+}
+
Added: trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.h (0 => 162825)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.h (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedInstructionStream.h 2014-01-27 05:45:30 UTC (rev 162825)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 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 UnlinkedInstructionStream_h
+#define UnlinkedInstructionStream_h
+
+#include "UnlinkedCodeBlock.h"
+#include <wtf/RefCountedArray.h>
+
+namespace JSC {
+
+class UnlinkedInstructionStream {
+public:
+ explicit UnlinkedInstructionStream(const Vector<UnlinkedInstruction>&);
+
+ unsigned count() const { return m_instructionCount; }
+
+ class Reader {
+ public:
+ explicit Reader(const UnlinkedInstructionStream&);
+
+ const UnlinkedInstruction* next();
+ bool atEnd() const { return m_index == m_stream.m_data.size(); }
+
+ private:
+ unsigned char read8();
+ unsigned read32();
+
+ const UnlinkedInstructionStream& m_stream;
+ UnlinkedInstruction m_unpackedBuffer[16];
+ unsigned m_index;
+ };
+
+#ifndef NDEBUG
+ const RefCountedArray<UnlinkedInstruction>& unpackForDebugging() const;
+#endif
+
+private:
+ friend class Reader;
+
+#ifndef NDEBUG
+ mutable RefCountedArray<UnlinkedInstruction> m_unpackedInstructionsForDebugging;
+#endif
+
+ RefCountedArray<unsigned char> m_data;
+ unsigned m_instructionCount;
+};
+
+} // namespace JSC
+
+#endif // UnlinkedInstructionStream_h
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (162824 => 162825)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2014-01-27 05:44:39 UTC (rev 162824)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2014-01-27 05:45:30 UTC (rev 162825)
@@ -41,6 +41,7 @@
#include "StackAlignment.h"
#include "StrongInlines.h"
#include "UnlinkedCodeBlock.h"
+#include "UnlinkedInstructionStream.h"
#include <wtf/StdLibExtras.h>
#include <wtf/text/WTFString.h>
@@ -106,7 +107,7 @@
m_codeBlock->addExceptionHandler(info);
}
- m_codeBlock->instructions() = RefCountedArray<UnlinkedInstruction>(m_instructions);
+ m_codeBlock->setInstructions(std::make_unique<UnlinkedInstructionStream>(m_instructions));
m_codeBlock->shrinkToFit();