dvander@85: /* dvander@85: * Copyright (C) 2012 David Anderson dvander@85: * dvander@85: * This file is part of JITCraft. dvander@85: * dvander@85: * JITCraft is free software: you can redistribute it and/or modify it under dvander@85: * the terms of the GNU General Public License as published by the Free dvander@85: * Software Foundation, either version 3 of the License, or (at your option) dvander@85: * any later version. dvander@85: * dvander@85: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@85: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@85: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@85: * dvander@85: * You should have received a copy of the GNU General Public License along with dvander@85: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@85: */ dvander@85: #ifndef _include_ke_environment_h_ dvander@85: #define _include_ke_environment_h_ dvander@85: dvander@85: #include "Objects.h" dvander@85: #include "Handles.h" dvander@85: #include "Heap.h" dvander@85: #include "FixedArray.h" dvander@85: dvander@85: namespace ke { dvander@85: dvander@85: class EnvironmentMap; dvander@85: class Variable; dvander@85: class ByteArray; dvander@85: class Type; dvander@85: dvander@85: // An environment represents the lexical environment of a code or function dvander@85: // object. It used for variables which may be accessed outside a function's dvander@85: // normal activation (i.e., upvars). dvander@85: // dvander@85: // A module uses an Environment to store its global variables. dvander@85: class Environment : public Object dvander@85: { dvander@85: template dvander@85: inline T *pointerToSlot(unsigned slot); dvander@85: dvander@85: public: dvander@85: static Environment *New(Zone *zone, Handle map, Heap::Tenure tenure = Heap::Tenure_Default); dvander@85: dvander@85: inline EnvironmentMap *map(); dvander@85: inline size_t size(); dvander@85: dvander@85: float getFloat(unsigned slot) { dvander@85: return *pointerToSlot(slot); dvander@85: } dvander@85: int getInt32(unsigned slot) { dvander@85: return *pointerToSlot(slot); dvander@85: } dvander@85: Object *getObject(unsigned slot) { dvander@85: return *pointerToSlot(slot); dvander@85: } dvander@85: void setFloat(unsigned slot, float f) { dvander@85: *pointerToSlot(slot) = f; dvander@85: } dvander@85: void setInt32(unsigned slot, int i) { dvander@85: *pointerToSlot(slot) = i; dvander@85: } dvander@85: void setObject(unsigned slot, Object *obj) { dvander@85: // :TODO: write barrier dvander@85: *pointerToSlot(slot) = obj; dvander@85: } dvander@85: dvander@85: static inline size_t offsetOfSlotOffset(unsigned offset) { dvander@85: return sizeof(Environment) + offset; dvander@85: } dvander@85: dvander@85: static inline Environment *cast(Object *obj) { dvander@85: assert(!obj || obj->is(MapKind_Environment)); dvander@85: return reinterpret_cast(obj); dvander@85: } dvander@85: }; dvander@85: dvander@85: struct EnvironmentSlotDescriptor dvander@85: { dvander@85: Barriered type; dvander@85: unsigned offset; dvander@85: }; dvander@85: dvander@85: class EnvironmentSlotDescriptorArray : public Object dvander@85: { dvander@85: unsigned length_; dvander@85: dvander@85: public: dvander@85: static EnvironmentSlotDescriptorArray *New(Zone *zone, unsigned length); dvander@85: dvander@85: EnvironmentSlotDescriptor *slots() { dvander@85: return reinterpret_cast(this + 1); dvander@85: } dvander@85: EnvironmentSlotDescriptor &at(unsigned slot) { dvander@85: assert(slot < length_); dvander@85: return slots()[slot]; dvander@85: } dvander@85: unsigned length() { dvander@85: return length_; dvander@85: } dvander@85: unsigned size() { dvander@85: return Align(sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray), dvander@85: kObjectAlignment); dvander@85: } dvander@85: dvander@85: static inline EnvironmentSlotDescriptorArray *cast(Object *obj) { dvander@85: assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray)); dvander@85: return reinterpret_cast(obj); dvander@85: } dvander@85: }; dvander@85: dvander@85: class EnvironmentMap : public Map dvander@85: { dvander@85: unsigned structureSize_; dvander@85: unsigned traceOffsetCount_; dvander@85: Barriered slots_; dvander@85: dvander@85: public: dvander@85: static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars); dvander@85: dvander@85: unsigned structureSize() { dvander@85: return structureSize_; dvander@85: } dvander@85: unsigned traceOffsetCount() { dvander@85: return traceOffsetCount_; dvander@85: } dvander@85: const unsigned *traceOffsets() { dvander@85: return reinterpret_cast(this + 1); dvander@85: } dvander@85: size_t size() { dvander@85: return Align(sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment); dvander@85: } dvander@85: EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) { dvander@85: return slots_->at(slot); dvander@85: } dvander@85: dvander@85: static inline size_t offsetOfSlots() { dvander@85: return offsetof(EnvironmentMap, slots_); dvander@85: } dvander@85: dvander@85: static inline EnvironmentMap *cast(Object *obj) { dvander@85: assert(!obj || obj->is(MapKind_MetaEnvironment)); dvander@85: return reinterpret_cast(obj); dvander@85: } dvander@85: }; dvander@85: dvander@85: size_t dvander@85: Environment::size() dvander@85: { dvander@85: return Align(sizeof(Environment) + map()->structureSize(), kObjectAlignment); dvander@85: } dvander@85: dvander@85: EnvironmentMap * dvander@85: Environment::map() dvander@85: { dvander@85: return EnvironmentMap::cast(Object::map()); dvander@85: } dvander@85: dvander@85: template T * dvander@85: Environment::pointerToSlot(unsigned slot) dvander@85: { dvander@85: return reinterpret_cast(reinterpret_cast(this + 1) + map()->slotDescriptor(slot).offset); dvander@85: } dvander@85: dvander@85: } dvander@85: dvander@85: #endif // _include_ke_environment_h_