Commit 85eb7df9 authored by fpizlo@apple.com's avatar fpizlo@apple.com

It should be possible to hijack IndexingHeader for things other than lengths

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

Reviewed by Mark Hahnenberg.
        
Made the body of IndexingHeader be a union.
        
Modified the offlineasm so that you can say IndexingHeader::u.lengths.publicLength.
Previously those dots would cause parse errors. Now an identifier in offlineasm can
have a dot anywhere except the first character.

* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* offlineasm/parser.rb:
* runtime/IndexingHeader.h:
(JSC::IndexingHeader::offsetOfPublicLength):
(JSC::IndexingHeader::offsetOfVectorLength):
(JSC::IndexingHeader::IndexingHeader):
(JSC::IndexingHeader::vectorLength):
(JSC::IndexingHeader::setVectorLength):
(JSC::IndexingHeader::publicLength):
(JSC::IndexingHeader::setPublicLength):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153104 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7e9bb4ce
2013-07-24 Filip Pizlo <fpizlo@apple.com>
It should be possible to hijack IndexingHeader for things other than lengths
https://bugs.webkit.org/show_bug.cgi?id=119065
Reviewed by Mark Hahnenberg.
Made the body of IndexingHeader be a union.
Modified the offlineasm so that you can say IndexingHeader::u.lengths.publicLength.
Previously those dots would cause parse errors. Now an identifier in offlineasm can
have a dot anywhere except the first character.
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* offlineasm/parser.rb:
* runtime/IndexingHeader.h:
(JSC::IndexingHeader::offsetOfPublicLength):
(JSC::IndexingHeader::offsetOfVectorLength):
(JSC::IndexingHeader::IndexingHeader):
(JSC::IndexingHeader::vectorLength):
(JSC::IndexingHeader::setVectorLength):
(JSC::IndexingHeader::publicLength):
(JSC::IndexingHeader::setPublicLength):
2013-07-24 Mark Hahnenberg <mhahnenberg@apple.com> 2013-07-24 Mark Hahnenberg <mhahnenberg@apple.com>
JIT::updateTopCallFrame doesn't update the CallFrame's bytecodeOffset if bytecodeOffset == 0 JIT::updateTopCallFrame doesn't update the CallFrame's bytecodeOffset if bytecodeOffset == 0
......
...@@ -1047,7 +1047,7 @@ _llint_op_get_array_length: ...@@ -1047,7 +1047,7 @@ _llint_op_get_array_length:
loadi 4[PC], t1 loadi 4[PC], t1
loadp 32[PC], t2 loadp 32[PC], t2
loadp JSObject::m_butterfly[t3], t0 loadp JSObject::m_butterfly[t3], t0
loadi -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], t0 loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
bilt t0, 0, .opGetArrayLengthSlow bilt t0, 0, .opGetArrayLengthSlow
valueProfile(Int32Tag, t0, t2) valueProfile(Int32Tag, t0, t2)
storep t0, PayloadOffset[cfr, t1, 8] storep t0, PayloadOffset[cfr, t1, 8]
...@@ -1182,14 +1182,14 @@ _llint_op_get_by_val: ...@@ -1182,14 +1182,14 @@ _llint_op_get_by_val:
bineq t2, ContiguousShape, .opGetByValNotContiguous bineq t2, ContiguousShape, .opGetByValNotContiguous
.opGetByValIsContiguous: .opGetByValIsContiguous:
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
loadi TagOffset[t3, t1, 8], t2 loadi TagOffset[t3, t1, 8], t2
loadi PayloadOffset[t3, t1, 8], t1 loadi PayloadOffset[t3, t1, 8], t1
jmp .opGetByValDone jmp .opGetByValDone
.opGetByValNotContiguous: .opGetByValNotContiguous:
bineq t2, DoubleShape, .opGetByValNotDouble bineq t2, DoubleShape, .opGetByValNotDouble
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
loadd [t3, t1, 8], ft0 loadd [t3, t1, 8], ft0
bdnequn ft0, ft0, .opGetByValSlow bdnequn ft0, ft0, .opGetByValSlow
# FIXME: This could be massively optimized. # FIXME: This could be massively optimized.
...@@ -1200,7 +1200,7 @@ _llint_op_get_by_val: ...@@ -1200,7 +1200,7 @@ _llint_op_get_by_val:
.opGetByValNotDouble: .opGetByValNotDouble:
subi ArrayStorageShape, t2 subi ArrayStorageShape, t2
bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2 loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2
loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1 loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1
...@@ -1282,20 +1282,20 @@ _llint_op_get_by_pname: ...@@ -1282,20 +1282,20 @@ _llint_op_get_by_pname:
macro contiguousPutByVal(storeCallback) macro contiguousPutByVal(storeCallback)
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .outOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
.storeResult: .storeResult:
loadi 12[PC], t2 loadi 12[PC], t2
storeCallback(t2, t1, t0, t3) storeCallback(t2, t1, t0, t3)
dispatch(5) dispatch(5)
.outOfBounds: .outOfBounds:
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValOutOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
if VALUE_PROFILER if VALUE_PROFILER
loadp 16[PC], t2 loadp 16[PC], t2
storeb 1, ArrayProfile::m_mayStoreToHole[t2] storeb 1, ArrayProfile::m_mayStoreToHole[t2]
end end
addi 1, t3, t2 addi 1, t3, t2
storei t2, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0] storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
jmp .storeResult jmp .storeResult
end end
...@@ -1349,7 +1349,7 @@ _llint_op_put_by_val: ...@@ -1349,7 +1349,7 @@ _llint_op_put_by_val:
.opPutByValNotContiguous: .opPutByValNotContiguous:
bineq t2, ArrayStorageShape, .opPutByValSlow bineq t2, ArrayStorageShape, .opPutByValSlow
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValOutOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
bieq ArrayStorage::m_vector + TagOffset[t0, t3, 8], EmptyValueTag, .opPutByValArrayStorageEmpty bieq ArrayStorage::m_vector + TagOffset[t0, t3, 8], EmptyValueTag, .opPutByValArrayStorageEmpty
.opPutByValArrayStorageStoreResult: .opPutByValArrayStorageStoreResult:
loadi 12[PC], t2 loadi 12[PC], t2
...@@ -1365,9 +1365,9 @@ _llint_op_put_by_val: ...@@ -1365,9 +1365,9 @@ _llint_op_put_by_val:
storeb 1, ArrayProfile::m_mayStoreToHole[t1] storeb 1, ArrayProfile::m_mayStoreToHole[t1]
end end
addi 1, ArrayStorage::m_numValuesInVector[t0] addi 1, ArrayStorage::m_numValuesInVector[t0]
bib t3, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .opPutByValArrayStorageStoreResult bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
addi 1, t3, t1 addi 1, t3, t1
storei t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0] storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
jmp .opPutByValArrayStorageStoreResult jmp .opPutByValArrayStorageStoreResult
.opPutByValOutOfBounds: .opPutByValOutOfBounds:
......
...@@ -889,7 +889,7 @@ _llint_op_get_array_length: ...@@ -889,7 +889,7 @@ _llint_op_get_array_length:
loadisFromInstruction(1, t1) loadisFromInstruction(1, t1)
loadpFromInstruction(8, t2) loadpFromInstruction(8, t2)
loadp JSObject::m_butterfly[t3], t0 loadp JSObject::m_butterfly[t3], t0
loadi -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], t0 loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0
bilt t0, 0, .opGetArrayLengthSlow bilt t0, 0, .opGetArrayLengthSlow
orq tagTypeNumber, t0 orq tagTypeNumber, t0
valueProfile(t0, t2) valueProfile(t0, t2)
...@@ -1022,7 +1022,7 @@ _llint_op_get_by_val: ...@@ -1022,7 +1022,7 @@ _llint_op_get_by_val:
bineq t2, ContiguousShape, .opGetByValNotContiguous bineq t2, ContiguousShape, .opGetByValNotContiguous
.opGetByValIsContiguous: .opGetByValIsContiguous:
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
loadisFromInstruction(1, t0) loadisFromInstruction(1, t0)
loadq [t3, t1, 8], t2 loadq [t3, t1, 8], t2
btqz t2, .opGetByValOutOfBounds btqz t2, .opGetByValOutOfBounds
...@@ -1030,7 +1030,7 @@ _llint_op_get_by_val: ...@@ -1030,7 +1030,7 @@ _llint_op_get_by_val:
.opGetByValNotContiguous: .opGetByValNotContiguous:
bineq t2, DoubleShape, .opGetByValNotDouble bineq t2, DoubleShape, .opGetByValNotDouble
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t3], .opGetByValOutOfBounds
loadis 8[PB, PC, 8], t0 loadis 8[PB, PC, 8], t0
loadd [t3, t1, 8], ft0 loadd [t3, t1, 8], ft0
bdnequn ft0, ft0, .opGetByValOutOfBounds bdnequn ft0, ft0, .opGetByValOutOfBounds
...@@ -1041,7 +1041,7 @@ _llint_op_get_by_val: ...@@ -1041,7 +1041,7 @@ _llint_op_get_by_val:
.opGetByValNotDouble: .opGetByValNotDouble:
subi ArrayStorageShape, t2 subi ArrayStorageShape, t2
bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow bia t2, SlowPutArrayStorageShape - ArrayStorageShape, .opGetByValSlow
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t3], .opGetByValOutOfBounds biaeq t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t3], .opGetByValOutOfBounds
loadisFromInstruction(1, t0) loadisFromInstruction(1, t0)
loadq ArrayStorage::m_vector[t3, t1, 8], t2 loadq ArrayStorage::m_vector[t3, t1, 8], t2
btqz t2, .opGetByValOutOfBounds btqz t2, .opGetByValOutOfBounds
...@@ -1120,20 +1120,20 @@ _llint_op_get_by_pname: ...@@ -1120,20 +1120,20 @@ _llint_op_get_by_pname:
macro contiguousPutByVal(storeCallback) macro contiguousPutByVal(storeCallback)
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .outOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .outOfBounds
.storeResult: .storeResult:
loadisFromInstruction(3, t2) loadisFromInstruction(3, t2)
storeCallback(t2, t1, [t0, t3, 8]) storeCallback(t2, t1, [t0, t3, 8])
dispatch(5) dispatch(5)
.outOfBounds: .outOfBounds:
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValOutOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
if VALUE_PROFILER if VALUE_PROFILER
loadp 32[PB, PC, 8], t2 loadp 32[PB, PC, 8], t2
storeb 1, ArrayProfile::m_mayStoreToHole[t2] storeb 1, ArrayProfile::m_mayStoreToHole[t2]
end end
addi 1, t3, t2 addi 1, t3, t2
storei t2, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0] storei t2, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
jmp .storeResult jmp .storeResult
end end
...@@ -1184,7 +1184,7 @@ _llint_op_put_by_val: ...@@ -1184,7 +1184,7 @@ _llint_op_put_by_val:
.opPutByValNotContiguous: .opPutByValNotContiguous:
bineq t2, ArrayStorageShape, .opPutByValSlow bineq t2, ArrayStorageShape, .opPutByValSlow
biaeq t3, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValOutOfBounds biaeq t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.vectorLength[t0], .opPutByValOutOfBounds
btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty btqz ArrayStorage::m_vector[t0, t3, 8], .opPutByValArrayStorageEmpty
.opPutByValArrayStorageStoreResult: .opPutByValArrayStorageStoreResult:
loadisFromInstruction(3, t2) loadisFromInstruction(3, t2)
...@@ -1199,9 +1199,9 @@ _llint_op_put_by_val: ...@@ -1199,9 +1199,9 @@ _llint_op_put_by_val:
storeb 1, ArrayProfile::m_mayStoreToHole[t1] storeb 1, ArrayProfile::m_mayStoreToHole[t1]
end end
addi 1, ArrayStorage::m_numValuesInVector[t0] addi 1, ArrayStorage::m_numValuesInVector[t0]
bib t3, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0], .opPutByValArrayStorageStoreResult bib t3, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], .opPutByValArrayStorageStoreResult
addi 1, t3, t1 addi 1, t3, t1
storei t1, -sizeof IndexingHeader + IndexingHeader::m_publicLength[t0] storei t1, -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0]
jmp .opPutByValArrayStorageStoreResult jmp .opPutByValArrayStorageStoreResult
.opPutByValOutOfBounds: .opPutByValOutOfBounds:
......
...@@ -114,7 +114,7 @@ def lex(str, fileName) ...@@ -114,7 +114,7 @@ def lex(str, fileName)
end end
result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
lineNumber += 1 lineNumber += 1
when /\A[a-zA-Z]([a-zA-Z0-9_]*)/ when /\A[a-zA-Z]([a-zA-Z0-9_.]*)/
result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
when /\A\.([a-zA-Z0-9_]*)/ when /\A\.([a-zA-Z0-9_]*)/
result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) result << Token.new(CodeOrigin.new(fileName, lineNumber), $&)
...@@ -163,7 +163,7 @@ def isKeyword(token) ...@@ -163,7 +163,7 @@ def isKeyword(token)
end end
def isIdentifier(token) def isIdentifier(token)
token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token) token =~ /\A[a-zA-Z]([a-zA-Z0-9_.]*)\Z/ and not isKeyword(token)
end end
def isLabel(token) def isLabel(token)
......
...@@ -44,25 +44,25 @@ public: ...@@ -44,25 +44,25 @@ public:
static ptrdiff_t offsetOfIndexingHeader() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); } static ptrdiff_t offsetOfIndexingHeader() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, m_publicLength); } static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.publicLength); }
static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, m_vectorLength); } static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.vectorLength); }
IndexingHeader() IndexingHeader()
: m_publicLength(0)
, m_vectorLength(0)
{ {
u.lengths.publicLength = 0;
u.lengths.vectorLength = 0;
} }
uint32_t vectorLength() const { return m_vectorLength; } uint32_t vectorLength() const { return u.lengths.vectorLength; }
void setVectorLength(uint32_t length) void setVectorLength(uint32_t length)
{ {
RELEASE_ASSERT(length <= maximumLength); RELEASE_ASSERT(length <= maximumLength);
m_vectorLength = length; u.lengths.vectorLength = length;
} }
uint32_t publicLength() { return m_publicLength; } uint32_t publicLength() { return u.lengths.publicLength; }
void setPublicLength(uint32_t auxWord) { m_publicLength = auxWord; } void setPublicLength(uint32_t auxWord) { u.lengths.publicLength = auxWord; }
static IndexingHeader* from(Butterfly* butterfly) static IndexingHeader* from(Butterfly* butterfly)
{ {
...@@ -111,9 +111,13 @@ public: ...@@ -111,9 +111,13 @@ public:
private: private:
friend class LLIntOffsetsExtractor; friend class LLIntOffsetsExtractor;
uint32_t m_publicLength; // The meaning of this field depends on the array type, but for all JSArrays we rely on this being the publicly visible length (array.length). union {
uint32_t m_vectorLength; // The length of the indexed property storage. The actual size of the storage depends on this, and the type. struct {
uint32_t publicLength; // The meaning of this field depends on the array type, but for all JSArrays we rely on this being the publicly visible length (array.length).
uint32_t vectorLength; // The length of the indexed property storage. The actual size of the storage depends on this, and the type.
} lengths;
} u;
}; };
} // namespace JSC } // namespace JSC
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment