Skip to content

Commit 31bc5e6

Browse files
committed
[JSC] Merge boolean fields in JSRegExpStringIterator into a single bitfield
https://bugs.webkit.org/show_bug.cgi?id=305258 Reviewed by Yusuke Suzuki. The Global, FullUnicode, and Done fields are now stored as bit flags in a single Flags field, reducing the object size from 56 to 40 bytes. * Source/JavaScriptCore/builtins/RegExpStringIteratorPrototype.js: (next): Use bitwise operations to read/write flags. * Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp: (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry): * Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h: * Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp: (JSC::regExpStringIteratorInternalFieldIndex): * Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::handleIntrinsicCall): * Source/JavaScriptCore/runtime/JSRegExpStringIterator.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/JSRegExpStringIterator.h: * Source/JavaScriptCore/runtime/RegExpPrototype.cpp: (JSC::JSC_DEFINE_HOST_FUNCTION): Canonical link: https://commits.webkit.org/305552@main
1 parent 4c69307 commit 31bc5e6

8 files changed

Lines changed: 62 additions & 36 deletions

File tree

‎Source/JavaScriptCore/builtins/RegExpStringIteratorPrototype.js‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ function next()
3333
if (!@isRegExpStringIterator(this))
3434
@throwTypeError("%RegExpStringIteratorPrototype%.next requires |this| to be an RegExp String Iterator instance");
3535

36-
var done = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldDone);
37-
if (done)
36+
var flags = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldFlags);
37+
if (flags & @regExpStringIteratorFlagDone)
3838
return { value: @undefined, done: true };
3939

4040
var regExp = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldRegExp);
4141
var string = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldString);
42-
var global = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldGlobal);
43-
var fullUnicode = @getRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldFullUnicode);
42+
var global = flags & @regExpStringIteratorFlagGlobal;
43+
var fullUnicode = flags & @regExpStringIteratorFlagFullUnicode;
4444
var match = @regExpExec(regExp, string);
4545
if (match === null) {
46-
@putRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldDone, true);
46+
@putRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldFlags, flags | @regExpStringIteratorFlagDone);
4747
return { value: @undefined, done: true };
4848
}
4949

@@ -54,7 +54,7 @@ function next()
5454
regExp.lastIndex = @advanceStringIndex(string, thisIndex, fullUnicode);
5555
}
5656
} else
57-
@putRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldDone, true);
57+
@putRegExpStringIteratorInternalField(this, @regExpStringIteratorFieldFlags, flags | @regExpStringIteratorFlagDone);
5858

5959
return { value: match, done: false };
6060
}

‎Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,10 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
139139
m_wrapForValidIteratorFieldIteratedNextMethod.set(m_vm, jsNumber(static_cast<int32_t>(JSWrapForValidIterator::Field::IteratedNextMethod)));
140140
m_regExpStringIteratorFieldRegExp.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::RegExp)));
141141
m_regExpStringIteratorFieldString.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::String)));
142-
m_regExpStringIteratorFieldGlobal.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::Global)));
143-
m_regExpStringIteratorFieldFullUnicode.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::FullUnicode)));
144-
m_regExpStringIteratorFieldDone.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::Done)));
142+
m_regExpStringIteratorFieldFlags.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::Field::Flags)));
143+
m_regExpStringIteratorFlagGlobal.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::FlagBit::Global)));
144+
m_regExpStringIteratorFlagFullUnicode.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::FlagBit::FullUnicode)));
145+
m_regExpStringIteratorFlagDone.set(m_vm, jsNumber(static_cast<int32_t>(JSRegExpStringIterator::FlagBit::Done)));
145146
m_iteratorHelperFieldGenerator.set(m_vm, jsNumber(static_cast<int32_t>(JSIteratorHelper::Field::Generator)));
146147
m_iteratorHelperFieldUnderlyingIterator.set(m_vm, jsNumber(static_cast<int32_t>(JSIteratorHelper::Field::UnderlyingIterator)));
147148
m_disposableStackFieldState.set(m_vm, jsNumber(static_cast<int32_t>(JSDisposableStack::Field::State)));

‎Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,10 @@ enum class LinkTimeConstant : int32_t;
203203
macro(wrapForValidIteratorFieldIteratedNextMethod) \
204204
macro(regExpStringIteratorFieldRegExp) \
205205
macro(regExpStringIteratorFieldString) \
206-
macro(regExpStringIteratorFieldGlobal) \
207-
macro(regExpStringIteratorFieldFullUnicode) \
208-
macro(regExpStringIteratorFieldDone) \
206+
macro(regExpStringIteratorFieldFlags) \
207+
macro(regExpStringIteratorFlagGlobal) \
208+
macro(regExpStringIteratorFlagFullUnicode) \
209+
macro(regExpStringIteratorFlagDone) \
209210
macro(disposableStackFieldState) \
210211
macro(disposableStackFieldCapability) \
211212
macro(DisposableStackStatePending) \

‎Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,12 +1731,8 @@ static JSRegExpStringIterator::Field regExpStringIteratorInternalFieldIndex(Byte
17311731
return JSRegExpStringIterator::Field::RegExp;
17321732
if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_regExpStringIteratorFieldString)
17331733
return JSRegExpStringIterator::Field::String;
1734-
if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_regExpStringIteratorFieldGlobal)
1735-
return JSRegExpStringIterator::Field::Global;
1736-
if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_regExpStringIteratorFieldFullUnicode)
1737-
return JSRegExpStringIterator::Field::FullUnicode;
1738-
if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_regExpStringIteratorFieldDone)
1739-
return JSRegExpStringIterator::Field::Done;
1734+
if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_regExpStringIteratorFieldFlags)
1735+
return JSRegExpStringIterator::Field::Flags;
17401736
RELEASE_ASSERT_NOT_REACHED();
17411737
return JSRegExpStringIterator::Field::RegExp;
17421738
}

‎Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4559,8 +4559,11 @@ auto ByteCodeParser::handleIntrinsicCall(Node* callee, Operand resultOperand, Ca
45594559
Node* regExpStringIterator = addToGraph(NewInternalFieldObject, OpInfo(m_graph.registerStructure(globalObject->regExpStringIteratorStructure())));
45604560
addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSRegExpStringIterator::Field::RegExp)), regExpStringIterator, regExp);
45614561
addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSRegExpStringIterator::Field::String)), regExpStringIterator, string);
4562-
addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSRegExpStringIterator::Field::Global)), regExpStringIterator, global);
4563-
addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSRegExpStringIterator::Field::FullUnicode)), regExpStringIterator, fullUnicode);
4562+
// Combine global and fullUnicode into a single flags field: flags = global | (fullUnicode << 1)
4563+
Node* one = addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(1))));
4564+
Node* fullUnicodeShifted = addToGraph(ArithBitLShift, fullUnicode, one);
4565+
Node* flags = addToGraph(ArithBitOr, global, fullUnicodeShifted);
4566+
addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSRegExpStringIterator::Field::Flags)), regExpStringIterator, flags);
45644567
setResult(regExpStringIterator);
45654568
return CallOptimizationResult::Inlined;
45664569
}

‎Source/JavaScriptCore/runtime/JSRegExpStringIterator.cpp‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ JSC_DEFINE_HOST_FUNCTION(regExpStringIteratorPrivateFuncCreate, (JSGlobalObject*
7373

7474
regExpStringIterator->setRegExp(vm, asObject(callFrame->uncheckedArgument(0)));
7575
regExpStringIterator->setString(vm, callFrame->uncheckedArgument(1));
76-
regExpStringIterator->setGlobal(vm, callFrame->argument(2));
77-
regExpStringIterator->setFullUnicode(vm, callFrame->argument(3));
76+
regExpStringIterator->setFlags(callFrame->argument(2).asBoolean(), callFrame->argument(3).asBoolean());
7877

7978
return JSValue::encode(regExpStringIterator);
8079
}

‎Source/JavaScriptCore/runtime/JSRegExpStringIterator.h‎

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
namespace JSC {
3131

32-
const static uint8_t JSRegExpStringIteratorNumberOfInternalFields = 5;
32+
const static uint8_t JSRegExpStringIteratorNumberOfInternalFields = 3;
3333

3434
class JSRegExpStringIterator final : public JSInternalFieldObjectImpl<JSRegExpStringIteratorNumberOfInternalFields> {
3535
public:
@@ -42,21 +42,22 @@ class JSRegExpStringIterator final : public JSInternalFieldObjectImpl<JSRegExpSt
4242
enum class Field : uint8_t {
4343
RegExp = 0,
4444
String,
45-
// FIXME: Global and FullUnicode should be one bitset field
46-
Global,
47-
FullUnicode,
48-
Done,
45+
Flags, // Global, FullUnicode, Done as bit flags
4946
};
5047
static_assert(numberOfInternalFields == JSRegExpStringIteratorNumberOfInternalFields);
5148

49+
enum class FlagBit : uint8_t {
50+
Global = 1 << 0,
51+
FullUnicode = 1 << 1,
52+
Done = 1 << 2,
53+
};
54+
5255
static std::array<JSValue, numberOfInternalFields> initialValues()
5356
{
5457
return { {
5558
jsNull(),
5659
jsNull(),
57-
jsBoolean(false),
58-
jsBoolean(false),
59-
jsBoolean(false),
60+
jsNumber(0),
6061
} };
6162
}
6263

@@ -73,12 +74,39 @@ class JSRegExpStringIterator final : public JSInternalFieldObjectImpl<JSRegExpSt
7374

7475
static JSRegExpStringIterator* createWithInitialValues(VM&, Structure*);
7576

77+
bool isGlobal() const { return flags() & static_cast<uint8_t>(FlagBit::Global); }
78+
bool isFullUnicode() const { return flags() & static_cast<uint8_t>(FlagBit::FullUnicode); }
79+
bool isDone() const { return flags() & static_cast<uint8_t>(FlagBit::Done); }
80+
7681
void setRegExp(VM& vm, JSObject* regExp) { internalField(Field::RegExp).set(vm, this, regExp); }
7782
void setString(VM& vm, JSValue string) { internalField(Field::String).set(vm, this, string); }
78-
void setGlobal(VM& vm, JSValue global) { internalField(Field::Global).set(vm, this, global); }
79-
void setFullUnicode(VM& vm, JSValue fullUnicode) { internalField(Field::FullUnicode).set(vm, this, fullUnicode); }
83+
void setGlobal(bool global) { setFlag(FlagBit::Global, global); }
84+
void setFullUnicode(bool fullUnicode) { setFlag(FlagBit::FullUnicode, fullUnicode); }
85+
void setDone(bool done) { setFlag(FlagBit::Done, done); }
86+
void setFlags(bool global, bool fullUnicode, bool done = false)
87+
{
88+
uint8_t flagValue = 0;
89+
if (global)
90+
flagValue |= static_cast<uint8_t>(FlagBit::Global);
91+
if (fullUnicode)
92+
flagValue |= static_cast<uint8_t>(FlagBit::FullUnicode);
93+
if (done)
94+
flagValue |= static_cast<uint8_t>(FlagBit::Done);
95+
internalField(Field::Flags).setWithoutWriteBarrier(jsNumber(flagValue));
96+
}
8097

8198
private:
99+
uint8_t flags() const { return static_cast<uint8_t>(internalField(Field::Flags).get().asInt32()); }
100+
void setFlag(FlagBit bit, bool value)
101+
{
102+
uint8_t currentFlags = flags();
103+
if (value)
104+
currentFlags |= static_cast<uint8_t>(bit);
105+
else
106+
currentFlags &= ~static_cast<uint8_t>(bit);
107+
internalField(Field::Flags).setWithoutWriteBarrier(jsNumber(currentFlags));
108+
}
109+
82110
JSRegExpStringIterator(VM& vm, Structure* structure)
83111
: Base(vm, structure)
84112
{

‎Source/JavaScriptCore/runtime/RegExpPrototype.cpp‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,7 @@ JSC_DEFINE_HOST_FUNCTION(regExpProtoFuncMatchAll, (JSGlobalObject* globalObject,
12231223
auto* iterator = JSRegExpStringIterator::createWithInitialValues(vm, globalObject->regExpStringIteratorStructure());
12241224
iterator->setRegExp(vm, matcher);
12251225
iterator->setString(vm, string);
1226-
iterator->setGlobal(vm, jsBoolean(global));
1227-
iterator->setFullUnicode(vm, jsBoolean(fullUnicode));
1226+
iterator->setFlags(global, fullUnicode);
12281227

12291228
return JSValue::encode(iterator);
12301229
}
@@ -1280,8 +1279,7 @@ JSC_DEFINE_HOST_FUNCTION(regExpProtoFuncMatchAll, (JSGlobalObject* globalObject,
12801279

12811280
regExpStringIterator->setRegExp(vm, matcher);
12821281
regExpStringIterator->setString(vm, string);
1283-
regExpStringIterator->setGlobal(vm, jsBoolean(global));
1284-
regExpStringIterator->setFullUnicode(vm, jsBoolean(fullUnicode));
1282+
regExpStringIterator->setFlags(global, fullUnicode);
12851283

12861284
return JSValue::encode(regExpStringIterator);
12871285
}

0 commit comments

Comments
 (0)