Support FieldExpressions as references.
authorDavid Anderson <dvander@alliedmods.net>
Sun Aug 05 12:55:51 2012 -0700 (2012-08-05)
changeset 1643bf7c007883d
parent 163 efc3f91dbe42
child 165 b67697fba413
Support FieldExpressions as references.
src/BytecodeCompiler.cpp
src/BytecodeEmitter.h
src/Interpreter.cpp
src/Messages.tbl
src/Opcodes.cpp
src/Opcodes.tbl
src/Reference.cpp
src/Reference.h
src/SemanticAnalysis.cpp
src/Structures.h
     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) {