Support FieldExpressions as references.
Support FieldExpressions as references.
1.1 --- a/src/BytecodeCompiler.cpp Sun Aug 05 02:17:40 2012 -0700
1.2 +++ b/src/BytecodeCompiler.cpp Sun Aug 05 12:55:51 2012 -0700
1.3 @@ -874,6 +874,11 @@
1.4 expr->right()->accept(this);
1.5 __ note_position(expr->pos());
1.6 __ arrayref_lifo();
1.7 + } else if (arg->isFieldExpression()) {
1.8 + FieldExpression *expr = arg->toFieldExpression();
1.9 + expr->left()->accept(this);
1.10 + __ note_position(expr->pos());
1.11 + __ fieldref_lifo(expr->fieldIndex());
1.12 } else {
1.13 // We don't know how to, or can't, build a direct reference to
1.14 // this type. Make an indirect one, by taking the top of the
2.1 --- a/src/BytecodeEmitter.h Sun Aug 05 02:17:40 2012 -0700
2.2 +++ b/src/BytecodeEmitter.h Sun Aug 05 12:55:51 2012 -0700
2.3 @@ -488,6 +488,13 @@
2.4 singleByteOp(OP_ARRAYREF_LIFO);
2.5 markOop(1);
2.6 }
2.7 + void fieldref_lifo(unsigned index) {
2.8 + recordOops();
2.9 + ensure(OP_FIELDREF_LIFO_LENGTH);
2.10 + writeOp(OP_FIELDREF_LIFO);
2.11 + writeUint32(index);
2.12 + markOop(1);
2.13 + }
2.14 void getref(Type *type) {
2.15 if (type->pod() == PrimitiveType_Int32) {
2.16 singleByteOp(OP_GETREF_I);
3.1 --- a/src/Interpreter.cpp Sun Aug 05 02:17:40 2012 -0700
3.2 +++ b/src/Interpreter.cpp Sun Aug 05 12:55:51 2012 -0700
3.3 @@ -835,7 +835,7 @@
3.4
3.5 case OP_ARRAYREF_LIFO:
3.6 {
3.7 - Local<Array> array(zone, top.sp[-2].array);
3.8 + Local<Array> array(zone, Array::cast(top.sp[-2].obj));
3.9 Local<Reference> ref(zone, Reference::NewArray(zone, array, top.sp[-1].i32, Heap::Tenure_Stack));
3.10 if (!ref)
3.11 goto error;
3.12 @@ -853,6 +853,15 @@
3.13 break;
3.14 }
3.15
3.16 +case OP_FIELDREF_LIFO:
3.17 +{
3.18 + Local<Struct> obj(zone, Struct::cast(top.sp[-1].obj));
3.19 + top.sp[-1].obj = Reference::NewField(zone, obj, READ_UINT32(top.pc), Heap::Tenure_Stack);
3.20 + if (!top.sp[-1].obj)
3.21 + goto error;
3.22 + break;
3.23 +}
3.24 +
3.25 case OP_GETREF_I:
3.26 {
3.27 top.sp[-1].i32 = top.sp[-1].ref->getInt();
4.1 --- a/src/Messages.tbl Sun Aug 05 02:17:40 2012 -0700
4.2 +++ b/src/Messages.tbl Sun Aug 05 12:55:51 2012 -0700
4.3 @@ -42,7 +42,8 @@
4.4 MSG(ExpectedGlobal, SyntaxError, "expected global variable or function")
4.5 MSG(ForwardNotImplemented, SyntaxError, "forward '%s' not implemented")
4.6 MSG(ForwardDeclareMismatches, SyntaxError, "declaration does not match original forward signature")
4.7 -MSG(ArrayCantBeReference, SyntaxError, "a parameter cannot be both an array and a reference")
4.8 +MSG(ArrayCantBeReference, SyntaxError, "redundant reference qualifier on array parameter")
4.9 +MSG(StructCantBeReference, SyntaxError, "redundant reference qualifier on struct parameter")
4.10 MSG(ArraySizeMustBeConstant, SyntaxError, "array size must be a constant integer")
4.11 MSG(ReferenceIsConstant, SyntaxError, "cannot assign to a constant lvalue")
4.12 MSG(MultiArrayInNative, SyntaxError, "multidimensional arrays cannot be passed to natives")
5.1 --- a/src/Opcodes.cpp Sun Aug 05 02:17:40 2012 -0700
5.2 +++ b/src/Opcodes.cpp Sun Aug 05 12:55:51 2012 -0700
5.3 @@ -281,6 +281,7 @@
5.4 case OP_SETGLOBAL_O:
5.5 case OP_GETFIELD:
5.6 case OP_SETFIELD:
5.7 + case OP_FIELDREF_LIFO:
5.8 fprintf(fp, "%u", READ_UINT32(pc));
5.9 break;
5.10
6.1 --- a/src/Opcodes.tbl Sun Aug 05 02:17:40 2012 -0700
6.2 +++ b/src/Opcodes.tbl Sun Aug 05 12:55:51 2012 -0700
6.3 @@ -259,3 +259,5 @@
6.4 OPDEF(OP_GETFIELD, 98, "getfield", 5, 1, 1)
6.5 OPDEF(OP_SETFIELD, 99, "setfield", 5, 2, 1)
6.6
6.7 +OPDEF(OP_FIELDREF_LIFO, 100, "fieldref.lifo", 5, 1, 1)
6.8 +
7.1 --- a/src/Reference.cpp Sun Aug 05 02:17:40 2012 -0700
7.2 +++ b/src/Reference.cpp Sun Aug 05 12:55:51 2012 -0700
7.3 @@ -18,6 +18,7 @@
7.4 #include "Reference.h"
7.5 #include "Zone.h"
7.6 #include "Array.h"
7.7 +#include "Structures.h"
7.8 #include "Heap-inl.h"
7.9
7.10 using namespace ke;
7.11 @@ -30,6 +31,7 @@
7.12 return NULL;
7.13
7.14 ref->location_ = location;
7.15 + ref->base_ = NULL;
7.16 return ref;
7.17 }
7.18
7.19 @@ -42,6 +44,7 @@
7.20
7.21 ref->location_ = &ref->slot_;
7.22 ref->slot_ = slot;
7.23 + ref->base_ = NULL;
7.24 return ref;
7.25 }
7.26
7.27 @@ -56,3 +59,17 @@
7.28 ref->base_ = base;
7.29 return ref;
7.30 }
7.31 +
7.32 +Reference *
7.33 +Reference::NewField(Zone *zone, Handle<Struct> obj, size_t index, Heap::Tenure tenure)
7.34 +{
7.35 + Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
7.36 + if (!ref)
7.37 + return NULL;
7.38 +
7.39 + Descriptor *desc = Descriptor::cast(obj->map()->type()->fields()->at(index));
7.40 + ref->location_ = obj->ref(desc);
7.41 + ref->base_ = obj;
7.42 + return ref;
7.43 +}
7.44 +
8.1 --- a/src/Reference.h Sun Aug 05 02:17:40 2012 -0700
8.2 +++ b/src/Reference.h Sun Aug 05 12:55:51 2012 -0700
8.3 @@ -25,18 +25,23 @@
8.4 namespace ke {
8.5
8.6 class Array;
8.7 +class Struct;
8.8
8.9 // A Reference is a typed pointer to another location in memory.
8.10 class Reference : public Object
8.11 {
8.12 void *location_;
8.13 + Barriered<Object> base_;
8.14 +
8.15 + // We do not compute references to objects, so this does not need to be
8.16 + // traced.
8.17 LocalSlot slot_;
8.18 - Barriered<Array> base_;
8.19
8.20 public:
8.21 static Reference *NewStack(Zone *zone, void *location, Heap::Tenure tenure = Heap::Tenure_Default);
8.22 static Reference *NewStack(Zone *zone, const LocalSlot &slot, Heap::Tenure tenure = Heap::Tenure_Default);
8.23 static Reference *NewArray(Zone *zone, Handle<Array> base, size_t index, Heap::Tenure tenure = Heap::Tenure_Default);
8.24 + static Reference *NewField(Zone *zone, Handle<Struct> obj, size_t index, Heap::Tenure tenure = Heap::Tenure_Default);
8.25
8.26 int getInt() {
8.27 return *reinterpret_cast<int *>(location_);
9.1 --- a/src/SemanticAnalysis.cpp Sun Aug 05 02:17:40 2012 -0700
9.2 +++ b/src/SemanticAnalysis.cpp Sun Aug 05 12:55:51 2012 -0700
9.3 @@ -860,6 +860,11 @@
9.4 return NULL;
9.5 }
9.6
9.7 + if (type->isStruct()) {
9.8 + cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
9.9 + return NULL;
9.10 + }
9.11 +
9.12 type = zone_->types()->getReference(type, parameter->isConst());
9.13 if (!type)
9.14 return false;
10.1 --- a/src/Structures.h Sun Aug 05 02:17:40 2012 -0700
10.2 +++ b/src/Structures.h Sun Aug 05 12:55:51 2012 -0700
10.3 @@ -160,17 +160,17 @@
10.4 return StructMap::cast(Object::map());
10.5 }
10.6
10.7 + void *ref(Descriptor *desc) {
10.8 + return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
10.9 + }
10.10 +
10.11 // This must NOT be used with any Object * type!
10.12 template <typename T> T get(Descriptor *desc) {
10.13 - return *reinterpret_cast<T *>(
10.14 - reinterpret_cast<Address>(this) +
10.15 - offsetOfSlotOffset(desc->offset()));
10.16 + return *reinterpret_cast<T *>(ref(desc));
10.17 }
10.18
10.19 template <typename T> void set(Descriptor *desc, const T &t) {
10.20 - *reinterpret_cast<T *>(
10.21 - reinterpret_cast<Address>(this) +
10.22 - offsetOfSlotOffset(desc->offset())) = t;
10.23 + *reinterpret_cast<T *>(ref(desc)) = t;
10.24 }
10.25
10.26 void set(Zone *zone, Descriptor *desc, Object *obj) {