Skip to content

Commit 3fee654

Browse files
Updating object proto representation to use TaggedProto
1 parent bf35bf7 commit 3fee654

File tree

4 files changed

+125
-22
lines changed

4 files changed

+125
-22
lines changed

notes/cacheir.cachet

+7-9
Original file line numberDiff line numberDiff line change
@@ -578,24 +578,22 @@ ir CacheIR emits MASM {
578578

579579
CacheIR::addFailurePath(out label failure);
580580

581-
label loopHead: MASM;
582581
label returnFalse: MASM;
583582
label returnTrue: MASM;
584583
label done: MASM;
585584

586-
emit MASM::BranchTestObject(Condition::NotEqual, lhsReg, returnFalse);
587-
emit MASM::UnboxObject(lhsReg, scratchReg);
588-
emit MASM::LoadObjectProto(scratchReg, lhsReg);
585+
emit MASM::FallibleUnboxObject(lhsReg, scratchReg, failure);
586+
emit MASM::LoadObjectProto(scratchReg, scratchReg);
589587

588+
label loopHead: MASM;
590589
bind loopHead;
591-
emit MASM::BranchTestNull(Condition::Equal, lhsReg, returnFalse);
592-
emit MASM::BranchTestMagic(Condition::Equal, lhsReg, failure);
593590

594-
emit MASM::BranchTestObject(Condition::NotEqual, lhsReg, returnFalse);
595-
emit MASM::UnboxObject(lhsReg, scratchReg);
591+
emit MASM::BranchTestNullProto(scratchReg, returnFalse);
592+
emit MASM::BranchTestLazyProto(scratchReg, failure);
593+
emit MASM::UnboxObjectProto(scratchReg, scratchReg);
596594
emit MASM::BranchObject(Condition::Equal, scratchReg, protoReg, returnTrue);
597595

598-
emit MASM::LoadObjectProto(scratchReg, lhsReg);
596+
emit MASM::LoadObjectProto(scratchReg, scratchReg);
599597
//emit MASM::StoreBool(true, protoReg); <-- uncomment to induce error
600598
emit MASM::Jump(loopHead);
601599

notes/js.cachet

+63-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum RegDataType {
99
NativeObjectSlots,
1010
NativeObjectElements,
1111
TypeTag,
12+
TaggedProto,
1213
}
1314

1415
struct RegData;
@@ -126,6 +127,28 @@ impl RegData {
126127

127128
unsafe fn toValueTypeUnchecked(data: RegData) -> ValueType;
128129

130+
fn isTaggedProto(data: RegData) -> Bool {
131+
RegData::typeOf(data) == RegDataType::TaggedProto
132+
}
133+
134+
fn fromTaggedProto(proto: TaggedProto) -> RegData {
135+
let data = (unsafe { RegData::fromTaggedProtoUnchecked(proto) });
136+
assume RegData::isTaggedProto(data);
137+
assume (unsafe { RegData::toTaggedProtoUnchecked(data) }) == proto;
138+
data
139+
}
140+
141+
unsafe fn fromTaggedProtoUnchecked(proto: TaggedProto) -> RegData;
142+
143+
fn toTaggedProto(data: RegData) -> TaggedProto {
144+
assert RegData::isTaggedProto(data);
145+
let proto = (unsafe { RegData::toTaggedProtoUnchecked(data) });
146+
assume (unsafe { RegData::fromTaggedProtoUnchecked(proto) }) == data;
147+
proto
148+
}
149+
150+
unsafe fn toTaggedProtoUnchecked(data: RegData) -> TaggedProto;
151+
129152
fn readData(data: RegData, offset: Int64) -> RegData {
130153
if RegData::isUnboxedValue(data) {
131154
let value = RegData::toUnboxedValue(data);
@@ -355,13 +378,7 @@ impl Object {
355378

356379
unsafe fn shapeOfUnchecked(heap: Heap, object: Object) -> Shape;
357380

358-
// #[reads(heap)]
359-
// fn protoOf(object: Object) -> Value;
360-
fn protoOf(object: Object) -> Value {
361-
(unsafe { Object::protoOfUnchecked(heap, object) })
362-
}
363-
364-
unsafe fn protoOfUnchecked(heap: Heap, object: Object) -> Value;
381+
365382

366383
fn toNativeObject(object: Object) -> NativeObject {
367384
let shape = Object::shapeOf(object);
@@ -617,6 +634,14 @@ struct BaseShape;
617634

618635
impl BaseShape {
619636
fn classOf(baseShape: BaseShape) -> Class;
637+
638+
// #[reads(heap)]
639+
// fn protoOf(object: Object) -> TaggedProto;
640+
fn protoOf(baseShape: BaseShape) -> TaggedProto {
641+
(unsafe { BaseShape::protoOfUnchecked(heap, baseShape) })
642+
}
643+
644+
unsafe fn protoOfUnchecked(heap: Heap, baseShape: BaseShape) -> TaggedProto;
620645
}
621646

622647
struct Shape;
@@ -668,3 +693,34 @@ struct String;
668693
struct Symbol;
669694

670695
struct BigInt;
696+
697+
enum ProtoTag {
698+
Null,
699+
Lazy,
700+
Object,
701+
}
702+
703+
struct TaggedProto;
704+
705+
impl TaggedProto {
706+
fn tag(proto: TaggedProto) -> ProtoTag;
707+
708+
fn isNull(proto: TaggedProto) -> Bool {
709+
TaggedProto::tag(proto) == ProtoTag::Null
710+
}
711+
712+
fn isLazy(proto: TaggedProto) -> Bool {
713+
TaggedProto::tag(proto) == ProtoTag::Lazy
714+
}
715+
716+
fn isObject(proto: TaggedProto) -> Bool {
717+
TaggedProto::tag(proto) == ProtoTag::Object
718+
}
719+
720+
fn toObject(proto: TaggedProto) -> Object {
721+
assert TaggedProto::isObject(proto);
722+
(unsafe { TaggedProto::toObjectUnchecked(proto) })
723+
}
724+
725+
unsafe fn toObjectUnchecked(proto: TaggedProto) -> Object;
726+
}

notes/masm.cachet

+52-2
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,28 @@ ir MASM {
231231
MASM::setObject(objectReg, Value::toObject(value));
232232
}
233233

234+
// Note: this is a no-op in Firefox since TaggedProtos
235+
// can be directly treated as Objects without explicit
236+
// unboxing.
237+
op UnboxObjectProto(srcReg: Reg, destReg: Reg) {
238+
let data = MASM::getData(srcReg);
239+
let proto = RegData::toTaggedProto(data);
240+
let object = TaggedProto::toObject(proto);
241+
MASM::setObject(destReg, object);
242+
}
243+
244+
op FallibleUnboxObject(valueReg: ValueReg, objectReg: Reg, label failure: MASM) {
245+
let value = MASM::getValue(valueReg);
246+
let valueIsObject = Value::isObject(value);
247+
248+
if !valueIsObject {
249+
goto failure;
250+
}
251+
252+
let object = Value::toObject(value);
253+
MASM::setObject(objectReg, object);
254+
}
255+
234256
op FallibleUnboxBoolean(valueReg: ValueReg, boolReg: Reg, label failure: MASM) {
235257
let value = MASM::getValue(valueReg);
236258
let valueIsBool = Value::isBool(value);
@@ -456,6 +478,28 @@ ir MASM {
456478
}
457479
}
458480

481+
// Note: this is a wrapper around branchTestPtr for when
482+
// the register contains a TaggedProto
483+
op BranchTestNullProto(reg: Reg, label branch: MASM) {
484+
let data = MASM::getData(reg);
485+
let proto = RegData::toTaggedProto(data);
486+
487+
if TaggedProto::isNull(proto) {
488+
goto branch;
489+
}
490+
}
491+
492+
// Note: this is a wrapper around branchPtr for when
493+
// the register contains a TaggedProto
494+
op BranchTestLazyProto(reg: Reg, label branch: MASM) {
495+
let data = MASM::getData(reg);
496+
let proto = RegData::toTaggedProto(data);
497+
498+
if TaggedProto::isLazy(proto) {
499+
goto branch;
500+
}
501+
}
502+
459503
op BranchTestNull(condition: Condition, valueReg: ValueReg, label branch: MASM) {
460504
let value = MASM::getValue(valueReg);
461505
let valueIsNull = Value::isNull(value);
@@ -937,9 +981,15 @@ ir MASM {
937981
MASM::setInt32(outputReg, length)
938982
}
939983

940-
op LoadObjectProto(objectReg: Reg, protoReg: ValueReg) {
984+
op LoadObjectProto(objectReg: Reg, protoReg: Reg) {
941985
let object = MASM::getObject(objectReg);
942-
MASM::setValue(protoReg, Object::protoOf(object));
986+
987+
let shape = Object::shapeOf(object);
988+
let baseShape = Shape::baseShapeOf(shape);
989+
let proto = BaseShape::protoOf(baseShape);
990+
let data = RegData::fromTaggedProto(proto);
991+
992+
MASM::setData(protoReg, data);
943993
}
944994

945995
fn getData(reg: Reg) -> RegData;

notes/stubs/instanceof.cachet

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import "../cacheir.cachet"
2+
import "../utils.cachet"
23

34
ir CacheStub emits CacheIR {
45
op InstanceOf(lhsId: ValueId, rhsId: ValueId) {
5-
CacheIR::initValueInput(lhsId);
6-
CacheIR::defineValueReg(lhsId);
7-
CacheIR::initValueInput(rhsId);
8-
CacheIR::defineValueReg(rhsId);
6+
initValueInput(lhsId);
7+
initValueInput(rhsId);
98

109
emit CacheIR::GuardToObject(rhsId);
1110
let protoId = ValueId::toObjectId(rhsId);

0 commit comments

Comments
 (0)