Skip to content

Commit

Permalink
Bug 58263 - Use EncodedValueDescriptor on both JSVALUE32_64, JSVALUE64
Browse files Browse the repository at this point in the history
Reviewed by Sam Weinig.

The JSJITInterface already uses EncodedValueDescriptor to access the tag/payload
separately on JSVALUE64, even though EncodedValueDescriptor is not used in
JSVALUE64's implementation of JSValue. Remove the separate definition for m_ptr
on X86_64. Using the union allows us to remove a layer of makeImmediate()/
immedaiteValue() methods.

* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JITInlineMethods.h:
(JSC::JIT::emitTagAsBoolImmediate):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_not):
(JSC::JIT::emit_op_jeq_null):
(JSC::JIT::emit_op_jneq_null):
(JSC::JIT::emit_op_get_pnames):
(JSC::JIT::emit_op_eq_null):
(JSC::JIT::emit_op_neq_null):
(JSC::JIT::emitSlow_op_not):
* runtime/JSCell.h:
* runtime/JSValue.h:
* runtime/JSValueInlineMethods.h:
(JSC::JSValue::encode):
(JSC::JSValue::decode):
(JSC::JSValue::operator==):
(JSC::JSValue::operator!=):
(JSC::JSValue::JSValue):
(JSC::JSValue::operator bool):
(JSC::JSValue::asInt32):
(JSC::JSValue::isUndefinedOrNull):
(JSC::JSValue::isBoolean):
(JSC::JSValue::isCell):
(JSC::JSValue::isInt32):
(JSC::JSValue::asDouble):
(JSC::JSValue::isNumber):
(JSC::JSValue::asCell):



Canonical link: https://commits.webkit.org/73281@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83517 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Gavin Barraclough committed Apr 11, 2011
1 parent f5f4237 commit 6e689e0
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 89 deletions.
44 changes: 44 additions & 0 deletions Source/JavaScriptCore/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
2011-04-11 Gavin Barraclough <barraclough@apple.com>

Reviewed by Sam Weinig.

Bug 58263 - Use EncodedValueDescriptor on both JSVALUE32_64, JSVALUE64

The JSJITInterface already uses EncodedValueDescriptor to access the tag/payload
separately on JSVALUE64, even though EncodedValueDescriptor is not used in
JSVALUE64's implementation of JSValue. Remove the separate definition for m_ptr
on X86_64. Using the union allows us to remove a layer of makeImmediate()/
immedaiteValue() methods.

* dfg/DFGNonSpeculativeJIT.cpp:
(JSC::DFG::NonSpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JITInlineMethods.h:
(JSC::JIT::emitTagAsBoolImmediate):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_not):
(JSC::JIT::emit_op_jeq_null):
(JSC::JIT::emit_op_jneq_null):
(JSC::JIT::emit_op_get_pnames):
(JSC::JIT::emit_op_eq_null):
(JSC::JIT::emit_op_neq_null):
(JSC::JIT::emitSlow_op_not):
* runtime/JSCell.h:
* runtime/JSValue.h:
* runtime/JSValueInlineMethods.h:
(JSC::JSValue::encode):
(JSC::JSValue::decode):
(JSC::JSValue::operator==):
(JSC::JSValue::operator!=):
(JSC::JSValue::JSValue):
(JSC::JSValue::operator bool):
(JSC::JSValue::asInt32):
(JSC::JSValue::isUndefinedOrNull):
(JSC::JSValue::isBoolean):
(JSC::JSValue::isCell):
(JSC::JSValue::isInt32):
(JSC::JSValue::asDouble):
(JSC::JSValue::isNumber):
(JSC::JSValue::asCell):

2011-04-11 Geoffrey Garen <ggaren@apple.com>

Try to fix a few builds.
Expand Down
10 changes: 5 additions & 5 deletions Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No
callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);

// If we add a DataFormatBool, we should use it here.
m_jit.xor32(TrustedImm32(FullTagTypeTrue), result.registerID());
m_jit.xor32(TrustedImm32(ValueTrue), result.registerID());
jsValueResult(result.gpr(), m_compileIndex);
break;
}
Expand All @@ -469,7 +469,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No

GPRResult result(this);
callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());

jsValueResult(result.gpr(), m_compileIndex);
break;
Expand All @@ -484,7 +484,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No

GPRResult result(this);
callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());

jsValueResult(result.gpr(), m_compileIndex);
break;
Expand All @@ -499,7 +499,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No

GPRResult result(this);
callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());

jsValueResult(result.gpr(), m_compileIndex);
break;
Expand All @@ -514,7 +514,7 @@ void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, No

GPRResult result(this);
callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());

jsValueResult(result.gpr(), m_compileIndex);
break;
Expand Down
12 changes: 6 additions & 6 deletions Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,9 +439,9 @@ bool SpeculativeJIT::compile(Node& node)
GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).

m_jit.move(value.registerID(), result.registerID());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(FullTagTypeFalse)), result.registerID());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.registerID());
speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.registerID(), TrustedImm32(static_cast<int32_t>(~1))));
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(FullTagTypeTrue)), result.registerID());
m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.registerID());

// If we add a DataFormatBool, we should use it here.
jsValueResult(result.gpr(), m_compileIndex);
Expand All @@ -456,7 +456,7 @@ bool SpeculativeJIT::compile(Node& node)
m_jit.set32Compare32(JITCompiler::LessThan, op1.registerID(), op2.registerID(), result.registerID());

// If we add a DataFormatBool, we should use it here.
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
jsValueResult(result.gpr(), m_compileIndex);
break;
}
Expand All @@ -469,7 +469,7 @@ bool SpeculativeJIT::compile(Node& node)
m_jit.set32Compare32(JITCompiler::LessThanOrEqual, op1.registerID(), op2.registerID(), result.registerID());

// If we add a DataFormatBool, we should use it here.
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
jsValueResult(result.gpr(), m_compileIndex);
break;
}
Expand All @@ -482,7 +482,7 @@ bool SpeculativeJIT::compile(Node& node)
m_jit.set32Compare32(JITCompiler::Equal, op1.registerID(), op2.registerID(), result.registerID());

// If we add a DataFormatBool, we should use it here.
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
jsValueResult(result.gpr(), m_compileIndex);
break;
}
Expand All @@ -495,7 +495,7 @@ bool SpeculativeJIT::compile(Node& node)
m_jit.set32Compare32(JITCompiler::Equal, op1.registerID(), op2.registerID(), result.registerID());

// If we add a DataFormatBool, we should use it here.
m_jit.or32(TrustedImm32(FullTagTypeFalse), result.registerID());
m_jit.or32(TrustedImm32(ValueFalse), result.registerID());
jsValueResult(result.gpr(), m_compileIndex);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/jit/JITInlineMethods.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID

ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
{
or32(TrustedImm32(static_cast<int32_t>(FullTagTypeFalse)), reg);
or32(TrustedImm32(static_cast<int32_t>(ValueFalse)), reg);
}

#endif // USE(JSVALUE32_64)
Expand Down
22 changes: 11 additions & 11 deletions Source/JavaScriptCore/jit/JITOpcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,9 +699,9 @@ void JIT::emit_op_not(Instruction* currentInstruction)
// Invert against JSValue(false); if the value was tagged as a boolean, then all bits will be
// clear other than the low bit (which will be 0 or 1 for false or true inputs respectively).
// Then invert against JSValue(true), which will add the tag back in, and flip the low bit.
xorPtr(TrustedImm32(static_cast<int32_t>(FullTagTypeFalse)), regT0);
xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0);
addSlowCase(branchTestPtr(NonZero, regT0, TrustedImm32(static_cast<int32_t>(~1))));
xorPtr(TrustedImm32(static_cast<int32_t>(FullTagTypeTrue)), regT0);
xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), regT0);

emitPutVirtualRegister(currentInstruction[1].u.operand);
}
Expand Down Expand Up @@ -736,7 +736,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)

// Now handle the immediate cases - undefined & null
isImmediate.link(this);
andPtr(TrustedImm32(~ExtendedTagBitUndefined), regT0);
andPtr(TrustedImm32(~TagBitUndefined), regT0);
addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target);

wasNotImmediate.link(this);
Expand All @@ -757,7 +757,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)

// Now handle the immediate cases - undefined & null
isImmediate.link(this);
andPtr(TrustedImm32(~ExtendedTagBitUndefined), regT0);
andPtr(TrustedImm32(~TagBitUndefined), regT0);
addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target);

wasNotImmediate.link(this);
Expand Down Expand Up @@ -914,8 +914,8 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)

isNotObject.link(this);
move(regT0, regT1);
and32(TrustedImm32(~ExtendedTagBitUndefined), regT1);
addJump(branch32(Equal, regT1, TrustedImm32(FullTagTypeNull)), breakTarget);
and32(TrustedImm32(~TagBitUndefined), regT1);
addJump(branch32(Equal, regT1, TrustedImm32(ValueNull)), breakTarget);

JITStubCall toObjectStubCall(this, cti_to_object);
toObjectStubCall.addArgument(regT0);
Expand Down Expand Up @@ -1168,8 +1168,8 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction)

isImmediate.link(this);

andPtr(TrustedImm32(~ExtendedTagBitUndefined), regT0);
setPtr(Equal, regT0, TrustedImm32(FullTagTypeNull), regT0);
andPtr(TrustedImm32(~TagBitUndefined), regT0);
setPtr(Equal, regT0, TrustedImm32(ValueNull), regT0);

wasNotImmediate.link(this);

Expand All @@ -1193,8 +1193,8 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)

isImmediate.link(this);

andPtr(TrustedImm32(~ExtendedTagBitUndefined), regT0);
setPtr(NotEqual, regT0, TrustedImm32(FullTagTypeNull), regT0);
andPtr(TrustedImm32(~TagBitUndefined), regT0);
setPtr(NotEqual, regT0, TrustedImm32(ValueNull), regT0);

wasNotImmediate.link(this);

Expand Down Expand Up @@ -1379,7 +1379,7 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas
void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
linkSlowCase(iter);
xorPtr(TrustedImm32(static_cast<int32_t>(FullTagTypeFalse)), regT0);
xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0);
JITStubCall stubCall(this, cti_op_not);
stubCall.addArgument(regT0);
stubCall.call(currentInstruction[1].u.operand);
Expand Down
8 changes: 0 additions & 8 deletions Source/JavaScriptCore/runtime/JSCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,6 @@ namespace JSC {
return false;
}

#if USE(JSVALUE64)
ALWAYS_INLINE JSCell* JSValue::asCell() const
{
ASSERT(isCell());
return m_ptr;
}
#endif // USE(JSVALUE64)

inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
{
return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
Expand Down
48 changes: 26 additions & 22 deletions Source/JavaScriptCore/runtime/JSValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace JSC {
#endif

union EncodedValueDescriptor {
EncodedJSValue asEncodedJSValue;
int64_t asInt64;
#if USE(JSVALUE32_64)
double asDouble;
#elif USE(JSVALUE64)
Expand Down Expand Up @@ -106,8 +106,8 @@ namespace JSC {
friend class SpecializedThunkJIT;

public:
static EncodedJSValue encode(JSValue value);
static JSValue decode(EncodedJSValue ptr);
static EncodedJSValue encode(JSValue);
static JSValue decode(EncodedJSValue);

enum JSNullTag { JSNull };
enum JSUndefinedTag { JSUndefined };
Expand Down Expand Up @@ -280,8 +280,6 @@ namespace JSC {

uint32_t tag() const;
int32_t payload() const;

EncodedValueDescriptor u;
#elif USE(JSVALUE64)
/*
* On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
Expand Down Expand Up @@ -327,7 +325,7 @@ namespace JSC {
* These values have the following properties:
* - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
* quickly distinguished from all immediate values, including these invalid pointers.
* - With bit 3 is masked out (ExtendedTagBitUndefined) Undefined and Null share the
* - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
* same value, allowing null & undefined to be quickly detected.
*
* No valid JSValue will have the bit pattern 0x0, this is used to represent array
Expand All @@ -336,30 +334,36 @@ namespace JSC {

// These values are #defines since using static const integers here is a ~1% regression!

// If all bits in the mask are set, this indicates an integer number,
// if any but not all are set this value is a double precision number.
#define TagTypeNumber 0xffff000000000000ll
// This value is 2^48, used to encode doubles such that the encoded value will begin
// with a 16-bit pattern within the range 0x0001..0xFFFE.
#define DoubleEncodeOffset 0x1000000000000ll
// The second bit set indicates an immediate other than a number (bool, null, undefined).
// If all bits in the mask are set, this indicates an integer number,
// if any but not all are set this value is a double precision number.
#define TagTypeNumber 0xffff000000000000ll

// All non-numeric (bool, null, undefined) immediates have bit 2 set.
#define TagBitTypeOther 0x2ll
#define TagBitBool 0x4ll
#define TagBitUndefined 0x8ll
// Combined integer value for non-numeric immediates.
#define ValueFalse (TagBitTypeOther | TagBitBool | false)
#define ValueTrue (TagBitTypeOther | TagBitBool | true)
#define ValueUndefined (TagBitTypeOther | TagBitUndefined)
#define ValueNull (TagBitTypeOther)

// TagMask is used to check for all types of immediate values (either number or 'other').
#define TagMask (TagTypeNumber | TagBitTypeOther)

#define ExtendedTagBitBool 0x4ll
#define ExtendedTagBitUndefined 0x8ll

#define FullTagTypeFalse (TagBitTypeOther | ExtendedTagBitBool | false)
#define FullTagTypeTrue (TagBitTypeOther | ExtendedTagBitBool | true)
#define FullTagTypeUndefined (TagBitTypeOther | ExtendedTagBitUndefined)
#define FullTagTypeNull (TagBitTypeOther)

static JSValue makeImmediate(intptr_t value);
intptr_t immediateValue() const;

JSCell* m_ptr;
// These special values are never visible to JavaScript code; Empty is used to represent
// Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
// These values would map to cell types in the JSValue encoding, but not valid GC cell
// pointer should have either of these values (Empty is null, deleted is at an invalid
// alignment for a GC cell, and in the zero page).
#define ValueEmpty 0x0ll
#define ValueDeleted 0x4ll
#endif

EncodedValueDescriptor u;
};

#if USE(JSVALUE32_64)
Expand Down

0 comments on commit 6e689e0

Please sign in to comment.