Skip to content
Permalink
Browse files
Sparse array size threshold should be increased to 100000
https://bugs.webkit.org/show_bug.cgi?id=100827

Patch by Filip Pizlo <fpizlo@apple.com> on 2012-10-31
Reviewed by Oliver Hunt.

This enables the use of contiguous arrays in programs that previously
couldn't use them. And I so far can't see any examples of this being
a downside. To the extent that there is a downside, it ought to be
addressed by GC: https://bugs.webkit.org/show_bug.cgi?id=100828

* runtime/ArrayConventions.h:
(JSC):



Canonical link: https://commits.webkit.org/118998@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@133131 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
pizlonator authored and Mark Lam committed Nov 1, 2012
1 parent 030783a commit c8cc86d439c7b395a8a74603af0c5643f2e36b3a
Showing 3 changed files with 160 additions and 27 deletions.
@@ -13,6 +13,32 @@
* runtime/ArrayConventions.h:
(JSC):

2012-10-31 Mark Lam <mark.lam@apple.com>

C++ llint 64-bit backend needs to zero extend results of int32 operations.
https://bugs.webkit.org/show_bug.cgi?id=100899.

Reviewed by Filip Pizlo.

llint asm instructions ending in "i" for a 64-bit machine expects the
high 32-bit of registers to be zero'ed out when a 32-bit instruction
writes into a register. Fixed the C++ llint to honor this.

Fixed the index register used in BaseIndex addressing to be of size
intptr_t as expected.

Updated CLoopRegister to handle different endiannesss configurations.

* llint/LowLevelInterpreter.cpp:
(JSC::CLoopRegister::clearHighWord):
- new method to clear the high 32-bit of a 64-bit register.
It's a no-op for the 32-bit build.
(CLoopRegister):
- CLoopRegister now takes care of packing and byte endianness order.
(JSC::CLoop::execute): - Added an assert.
* offlineasm/cloop.rb:
- Add calls to clearHighWord() wherever needed.

2012-10-31 Mark Lam <mark.lam@apple.com>

A JSC printf (support for %J+s and %b).
@@ -121,6 +121,98 @@ static double Ints2Double(uint32_t lo, uint32_t hi)
} // namespace LLint


//============================================================================
// CLoopRegister is the storage for an emulated CPU register.
// It defines the policy of how ints smaller than intptr_t are packed into the
// pseudo register, as well as hides endianness differences.

struct CLoopRegister {
union {
intptr_t i;
uintptr_t u;
#if USE(JSVALUE64)
#if CPU(BIG_ENDIAN)
struct {
int32_t i32padding;
int32_t i32;
};
struct {
uint32_t u32padding;
uint32_t u32;
};
struct {
int8_t i8padding[7];
int8_t i8;
};
struct {
uint8_t u8padding[7];
uint8_t u8;
};
#else // !CPU(BIG_ENDIAN)
struct {
int32_t i32;
int32_t i32padding;
};
struct {
uint32_t u32;
uint32_t u32padding;
};
struct {
int8_t i8;
int8_t i8padding[7];
};
struct {
uint8_t u8;
uint8_t u8padding[7];
};
#endif // !CPU(BIG_ENDIAN)
#else // !USE(JSVALUE64)
int32_t i32;
uint32_t u32;

#if CPU(BIG_ENDIAN)
struct {
int8_t i8padding[3];
int8_t i8;
};
struct {
uint8_t u8padding[3];
uint8_t u8;
};

#else // !CPU(BIG_ENDIAN)
struct {
int8_t i8;
int8_t i8padding[3];
};
struct {
uint8_t u8;
uint8_t u8padding[3];
};
#endif // !CPU(BIG_ENDIAN)
#endif // !USE(JSVALUE64)

int8_t* i8p;
void* vp;
ExecState* execState;
void* instruction;
NativeFunction nativeFunc;
#if USE(JSVALUE64)
int64_t i64;
uint64_t u64;
EncodedJSValue encodedJSValue;
double castToDouble;
#endif
Opcode opcode;
};

#if USE(JSVALUE64)
inline void clearHighWord() { i32padding = 0; }
#else
inline void clearHighWord() { }
#endif
};

//============================================================================
// The llint C++ interpreter loop:
//
@@ -164,26 +256,8 @@ JSValue CLoop::execute(CallFrame* callFrame, OpcodeID bootstrapOpcodeId,
ASSERT(callFrame->globalData().topCallFrame == callFrame);

// Define the pseudo registers used by the LLINT C Loop backend:
union CLoopRegister {
intptr_t i;
uintptr_t u;
int32_t i32;
uint32_t u32;
int8_t i8;
uint8_t u8;
int8_t* i8p;
void* vp;
ExecState* execState;
void* instruction;
NativeFunction nativeFunc;
#if USE(JSVALUE64)
int64_t i64;
uint64_t u64;
EncodedJSValue encodedJSValue;
double castToDouble;
#endif
Opcode opcode;
};
ASSERT(sizeof(CLoopRegister) == sizeof(intptr_t));

union CLoopDoubleRegister {
double d;
#if USE(JSVALUE64)
@@ -249,10 +249,10 @@ def clValue(type=:int)
end
def pointerExpr
if base.is_a? RegisterID and base.name == "sp"
offsetValue = "(#{index.clValue(:int32)} << #{scaleShift}) + #{offset.clValue})"
offsetValue = "(#{index.clValue} << #{scaleShift}) + #{offset.clValue})"
"(ASSERT(#{offsetValue} == offsetof(JITStackFrame, globalData)), &sp->globalData)"
else
"#{base.clValue(:int8Ptr)} + (#{index.clValue(:int32)} << #{scaleShift}) + #{offset.clValue}"
"#{base.clValue(:int8Ptr)} + (#{index.clValue} << #{scaleShift}) + #{offset.clValue}"
end
end
def int8MemRef
@@ -353,22 +353,47 @@ def clOperands(operands)


def cloopEmitOperation(operands, type, operator)
raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || \
type == :int64 || type == :uint64 || type == :double
if operands.size == 3
$asm.putc "#{operands[2].clValue(type)} = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
$asm.putc "#{operands[2].dump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
end
else
raise unless operands.size == 2
raise unless not operands[1].is_a? Immediate
$asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} #{operands[0].clValue(type)};"
if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
$asm.putc "#{operands[1].dump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
end
end
end

def cloopEmitShiftOperation(operands, type, operator)
raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || type == :int64 || type == :uint64
if operands.size == 3
$asm.putc "#{operands[2].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
if operands[2].is_a? RegisterID and (type == :int32 or type == :uint32)
$asm.putc "#{operands[2].dump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
end
else
raise unless operands.size == 2
raise unless not operands[1].is_a? Immediate
$asm.putc "#{operands[1].clValue(type)} = #{operands[1].clValue(type)} #{operator} (#{operands[0].clValue(:int)} & 0x1f);"
if operands[1].is_a? RegisterID and (type == :int32 or type == :uint32)
$asm.putc "#{operands[1].dump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
end
end
end

def cloopEmitUnaryOperation(operands, type, operator)
raise unless type == :int || type == :uint || type == :int32 || type == :uint32 || type == :int64 || type == :uint64
raise unless operands.size == 1
raise unless not operands[0].is_a? Immediate
$asm.putc "#{operands[0].clValue(type)} = #{operator}#{operands[0].clValue(type)};"
if operands[0].is_a? RegisterID and (type == :int32 or type == :uint32)
$asm.putc "#{operands[0].dump}.clearHighWord();" # Just clear it. It does nothing on the 32-bit port.
end
end

@@ -595,17 +620,19 @@ def lowerC_LOOP
cloopEmitOperation(operands, :int, "-")

when "negi"
$asm.putc "#{operands[0].clValue(:int32)} = -#{operands[0].clValue(:int32)};"
cloopEmitUnaryOperation(operands, :int32, "-")
when "negq"
$asm.putc "#{operands[0].clValue(:int64)} = -#{operands[0].clValue(:int64)};"
cloopEmitUnaryOperation(operands, :int64, "-")
when "negp"
$asm.putc "#{operands[0].clValue(:int)} = -#{operands[0].clValue(:int)};"
cloopEmitUnaryOperation(operands, :int, "-")

when "noti"
$asm.putc "#{operands[0].clValue(:int32)} = !#{operands[0].clValue(:int32)};"
cloopEmitUnaryOperation(operands, :int32, "!")

when "loadi"
$asm.putc "#{operands[1].clValue(:int)} = #{operands[0].uint32MemRef};"
$asm.putc "#{operands[1].clValue(:uint)} = #{operands[0].uint32MemRef};"
# There's no need to call clearHighWord() here because the above will
# automatically take care of 0 extension.
when "loadis"
$asm.putc "#{operands[1].clValue(:int)} = #{operands[0].int32MemRef};"
when "loadq"
@@ -676,6 +703,7 @@ def lowerC_LOOP

when "td2i"
$asm.putc "#{operands[1].clValue(:int)} = #{operands[0].clValue(:double)};"
$asm.putc "#{operands[1].dump}.clearHighWord();"

when "bcd2i" # operands: srcDbl dstInt slowPath
$asm.putc "{"
@@ -684,6 +712,7 @@ def lowerC_LOOP
$asm.putc " if (asInt32 != d || (!asInt32 && signbit(d))) // true for -0.0"
$asm.putc " goto #{operands[2].cLabel};"
$asm.putc " #{operands[1].clValue} = asInt32;"
$asm.putc " #{operands[1].dump}.clearHighWord();"
$asm.putc "}"

when "move"
@@ -965,7 +994,9 @@ def lowerC_LOOP
$asm.putc "{"
$asm.putc " int64_t temp = t0.i32; // sign extend the low 32bit"
$asm.putc " t0.i32 = temp; // low word"
$asm.putc " t0.clearHighWord();"
$asm.putc " t1.i32 = uint64_t(temp) >> 32; // high word"
$asm.putc " t1.clearHighWord();"
$asm.putc "}"

# 64-bit instruction: idivi op1 (based on X64)
@@ -985,7 +1016,9 @@ def lowerC_LOOP
$asm.putc " int64_t dividend = (int64_t(t1.u32) << 32) | t0.u32;"
$asm.putc " int64_t divisor = #{operands[0].clValue(:int)};"
$asm.putc " t1.i32 = dividend % divisor; // remainder"
$asm.putc " t1.clearHighWord();"
$asm.putc " t0.i32 = dividend / divisor; // quotient"
$asm.putc " t0.clearHighWord();"
$asm.putc "}"

# 32-bit instruction: fii2d int32LoOp int32HiOp dblOp (based on ARMv7)

0 comments on commit c8cc86d

Please sign in to comment.