Added global variable support.
Added global variable support.
1.1 --- a/jitcraft/API.cpp Fri Jul 20 00:03:10 2012 -0700
1.2 +++ b/jitcraft/API.cpp Mon Jul 23 01:19:44 2012 -0700
1.3 @@ -110,7 +110,17 @@
1.4 Scope::Allocate(tree);
1.5
1.6 BytecodeCompiler compiler(ZONE(), tree, NULL);
1.7 - return compiler.compile();
1.8 + ke::Local<Module> module(ke::ZONE(), compiler.compile());
1.9 + if (!module)
1.10 + return NULL;
1.11 +
1.12 + ke::InvokeArgs args;
1.13 + if (!ke::ZONE()->stack().pushModuleFrame(module, args))
1.14 + return NULL;
1.15 + if (!ke::Interpret(ke::ZONE(), NULL, NULL))
1.16 + return NULL;
1.17 +
1.18 + return module;
1.19 }
1.20
1.21 Ke::Local<Ke::Module>
2.1 --- a/jitcraft/Barriers.h Fri Jul 20 00:03:10 2012 -0700
2.2 +++ b/jitcraft/Barriers.h Mon Jul 23 01:19:44 2012 -0700
2.3 @@ -78,7 +78,7 @@
2.4 return *this;
2.5 }
2.6 Object **addr() {
2.7 - return &obj_;
2.8 + return reinterpret_cast<Object **>(&obj_);
2.9 }
2.10 operator bool () const {
2.11 return !!obj_;
3.1 --- a/jitcraft/BytecodeCompiler.cpp Fri Jul 20 00:03:10 2012 -0700
3.2 +++ b/jitcraft/BytecodeCompiler.cpp Mon Jul 23 01:19:44 2012 -0700
3.3 @@ -23,6 +23,7 @@
3.4 #include "Array.h"
3.5 #include "Strings.h"
3.6 #include "Zone.h"
3.7 +#include "Environments.h"
3.8 #include "Heap-inl.h"
3.9
3.10 using namespace ke;
3.11 @@ -156,6 +157,8 @@
3.12 if (var->location() == Variable::STACK) {
3.13 __ getlocal(var);
3.14 assert(!name->type()->isReference());
3.15 + } else if (var->location() == Variable::ENVIRONMENT) {
3.16 + getEnvSlot(var);
3.17 } else {
3.18 assert(var->location() == Variable::PARAMETER);
3.19 __ getarg(var);
3.20 @@ -697,16 +700,34 @@
3.21 }
3.22
3.23 void
3.24 +BytecodeCompiler::getEnvSlot(Variable *var)
3.25 +{
3.26 + assert(var->scope()->kind() == Scope::GLOBAL);
3.27 + __ getglobal(var);
3.28 +}
3.29 +
3.30 +void
3.31 +BytecodeCompiler::setEnvSlot(Variable *var)
3.32 +{
3.33 + assert(var->scope()->kind() == Scope::GLOBAL);
3.34 + __ setglobal(var);
3.35 +}
3.36 +
3.37 +void
3.38 BytecodeCompiler::visit(VariableDeclaration *node)
3.39 {
3.40 Variable *var = node->variable();
3.41 - assert(var->location() == Variable::STACK);
3.42
3.43 Local<Type> type(zone_, var->type());
3.44 if (type->isArray()) {
3.45 Local<ArrayMap> map(zone_, BuildArrayMap(zone_, type));
3.46 __ note_position(node->pos());
3.47 - __ newarray_lifo(map);
3.48 + if (var->scope()->kind() == Scope::GLOBAL)
3.49 + __ newarray(map, Heap::Tenure_Old);
3.50 + else if (var->needsHeapAllocation())
3.51 + __ newarray(map, Heap::Tenure_Default);
3.52 + else
3.53 + __ newarray(map, Heap::Tenure_Stack);
3.54
3.55 if (node->initialization()) {
3.56 node->initialization()->accept(this);
3.57 @@ -721,10 +742,16 @@
3.58 __ int_(0);
3.59 }
3.60 }
3.61 - __ setlocal(var);
3.62 +
3.63 + if (var->location() == Variable::STACK) {
3.64 + __ setlocal(var);
3.65 + locals_->set(zone_, var->slot(), var->type());
3.66 + } else {
3.67 + assert(var->location() == Variable::ENVIRONMENT);
3.68 + setEnvSlot(var);
3.69 + }
3.70 +
3.71 __ pop();
3.72 -
3.73 - locals_->set(zone_, var->slot(), var->type());
3.74 }
3.75
3.76 void
3.77 @@ -875,18 +902,9 @@
3.78 // :TODO: eventually, we'll export these.
3.79 }
3.80
3.81 -Function *
3.82 -BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
3.83 +Code *
3.84 +BytecodeCompiler::compileCode(Scope *scope, unsigned lineno)
3.85 {
3.86 - // Note: No need to record a life slot here, since it's part of the Frame.
3.87 - AutoEnterScope functionScope(this, node->scope());
3.88 -
3.89 - // Set the initial line, because line mappings are deltas.
3.90 - __ setFirstLine(node->pos().line);
3.91 - locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
3.92 -
3.93 - node->body()->accept(this);
3.94 -
3.95 // STOP doubles as RETURNVOID.
3.96 __ stop();
3.97
3.98 @@ -898,15 +916,7 @@
3.99 return NULL;
3.100 memcpy(bytes->raw(), __ buffer(), __ length());
3.101
3.102 - unsigned nargs = node->scope()->numArguments();
3.103 - Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
3.104 - if (!args)
3.105 - return NULL;
3.106 -
3.107 - for (size_t i = 0; i < node->scope()->numArguments(); i++)
3.108 - args->set(zone_, i, node->scope()->getArgument(i)->type());
3.109 -
3.110 - for (size_t i = 0; i < node->scope()->maxContainedLocals(); i++)
3.111 + for (size_t i = 0; i < scope->maxContainedLocals(); i++)
3.112 assert(locals_->at(i));
3.113
3.114 Local<FixedArray> objects(zone_, FixedArray::New(zone_, __ objects()->length(), Heap::Tenure_Old));
3.115 @@ -965,7 +975,32 @@
3.116 moduleData_->module,
3.117 safepoints,
3.118 sourcemap,
3.119 - node->pos().line);
3.120 + lineno);
3.121 + return code;
3.122 +}
3.123 +
3.124 +Function *
3.125 +BytecodeCompiler::compileFunction(ModuleData *module, FunctionStatement *node)
3.126 +{
3.127 + // Note: No need to record a life slot here, since it's part of the Frame.
3.128 + AutoEnterScope functionScope(this, node->scope());
3.129 +
3.130 + // Set the initial line, because line mappings are deltas.
3.131 + __ setFirstLine(node->pos().line);
3.132 + locals_ = FixedArray::New(zone_, node->scope()->maxContainedLocals(), Heap::Tenure_Old);
3.133 +
3.134 + node->body()->accept(this);
3.135 +
3.136 + unsigned nargs = node->scope()->numArguments();
3.137 + Local<FixedArray> args(zone_, FixedArray::New(zone_, nargs, Heap::Tenure_Old));
3.138 + if (!args)
3.139 + return NULL;
3.140 +
3.141 + for (size_t i = 0; i < node->scope()->numArguments(); i++)
3.142 + args->set(zone_, i, node->scope()->getArgument(i)->type());
3.143 +
3.144 +
3.145 + Local<Code> code(zone_, compileCode(node->scope(), node->pos().line));
3.146 if (!code)
3.147 return NULL;
3.148
3.149 @@ -993,6 +1028,8 @@
3.150 Module *
3.151 BytecodeCompiler::compile()
3.152 {
3.153 + AutoEnterScope scope(this, tree_->scope());
3.154 +
3.155 ModuleData moduleData;
3.156
3.157 moduleData_ = &moduleData;
3.158 @@ -1035,5 +1072,25 @@
3.159
3.160 moduleData_->module->setNatives(moduleData_->natives);
3.161
3.162 + if (scope_->numEnvironmentVars()) {
3.163 + Local<EnvironmentMap> globalMap(zone_, scope_->createEnvironmentMap(zone_));
3.164 + if (!globalMap)
3.165 + return NULL;
3.166 +
3.167 + Local<Environment> environment(zone_, Environment::New(zone_, globalMap));
3.168 + if (!environment)
3.169 + return NULL;
3.170 +
3.171 + moduleData_->module->setEnvironment(environment);
3.172 + }
3.173 +
3.174 + Local<Code> code(zone_, compileCode(tree_->scope(), 1));
3.175 + if (!code)
3.176 + return NULL;
3.177 +
3.178 + Disassemble(code, stdout);
3.179 +
3.180 + moduleData_->module->setCode(code);
3.181 +
3.182 return moduleData_->module;
3.183 }
4.1 --- a/jitcraft/BytecodeCompiler.h Fri Jul 20 00:03:10 2012 -0700
4.2 +++ b/jitcraft/BytecodeCompiler.h Mon Jul 23 01:19:44 2012 -0700
4.3 @@ -107,9 +107,13 @@
4.4 BytecodeEmitter::Label *trueBranch,
4.5 BytecodeEmitter::Label *falseBranch,
4.6 BytecodeEmitter::Label *fallthrough);
4.7 + Code *compileCode(Scope *scope, unsigned lineno);
4.8 Function *compileFunction(ModuleData *module, FunctionStatement *fun);
4.9 void visitForALU(Type *needed, Expression *node);
4.10
4.11 + void getEnvSlot(Variable *var);
4.12 + void setEnvSlot(Variable *var);
4.13 +
4.14 public:
4.15 BytecodeCompiler(Zone *zone, ParseTree *tree, ModuleData *module);
4.16
5.1 --- a/jitcraft/BytecodeEmitter.h Fri Jul 20 00:03:10 2012 -0700
5.2 +++ b/jitcraft/BytecodeEmitter.h Mon Jul 23 01:19:44 2012 -0700
5.3 @@ -364,6 +364,7 @@
5.4 writeUint32(index);
5.5 writeUint32(argc);
5.6 }
5.7 +
5.8 void getarray(PrimitiveType type) {
5.9 switch (type) {
5.10 case PrimitiveType_Float:
5.11 @@ -392,6 +393,43 @@
5.12 break;
5.13 }
5.14 }
5.15 +
5.16 + void getglobal(Variable *var) {
5.17 + ensure(OP_GETGLOBAL_F_LENGTH);
5.18 + if (var->type()->isPrimitive()) {
5.19 + switch (var->type()->primitive()) {
5.20 + case PrimitiveType_Float:
5.21 + writeOp(OP_GETGLOBAL_F);
5.22 + break;
5.23 + default:
5.24 + assert(var->type()->primitive() == PrimitiveType_Int32);
5.25 + writeOp(OP_GETGLOBAL_I);
5.26 + break;
5.27 + }
5.28 + } else {
5.29 + writeOp(OP_GETGLOBAL_O);
5.30 + markOop(1);
5.31 + }
5.32 + writeUint32(var->slot());
5.33 + }
5.34 + void setglobal(Variable *var) {
5.35 + ensure(OP_SETGLOBAL_F_LENGTH);
5.36 + if (var->type()->isPrimitive()) {
5.37 + switch (var->type()->primitive()) {
5.38 + case PrimitiveType_Float:
5.39 + writeOp(OP_SETGLOBAL_F);
5.40 + break;
5.41 + default:
5.42 + assert(var->type()->primitive() == PrimitiveType_Int32);
5.43 + writeOp(OP_SETGLOBAL_I);
5.44 + break;
5.45 + }
5.46 + } else {
5.47 + writeOp(OP_SETGLOBAL_O);
5.48 + }
5.49 + writeUint32(var->slot());
5.50 + }
5.51 +
5.52 void getarray_o() {
5.53 singleByteOp(OP_GETARRAY_O);
5.54 markOop(1);
5.55 @@ -408,10 +446,11 @@
5.56 void cvt_i2f() {
5.57 singleByteOp(OP_CVT_I2F);
5.58 }
5.59 - void newarray_lifo(Handle<Map> map) {
5.60 + void newarray(Handle<Map> map, Heap::Tenure tenure) {
5.61 recordOops();
5.62 - ensure(OP_NEWARRAY_LIFO_LENGTH);
5.63 - writeOp(OP_NEWARRAY_LIFO);
5.64 + ensure(OP_NEWARRAY_LENGTH);
5.65 + writeOp(OP_NEWARRAY);
5.66 + writeUint8(tenure);
5.67 writeObject(map);
5.68 markOop(1);
5.69 }
6.1 --- a/jitcraft/Code.h Fri Jul 20 00:03:10 2012 -0700
6.2 +++ b/jitcraft/Code.h Mon Jul 23 01:19:44 2012 -0700
6.3 @@ -69,7 +69,7 @@
6.4 return Type::cast(locals_->at(index));
6.5 }
6.6 unsigned nlocals() {
6.7 - return locals_->length();
6.8 + return locals_ ? locals_->length() : 0;
6.9 }
6.10 unsigned maxStackDepth() {
6.11 return maxStackDepth_;
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/jitcraft/Environments.cpp Mon Jul 23 01:19:44 2012 -0700
7.3 @@ -0,0 +1,97 @@
7.4 +/*
7.5 + * Copyright (C) 2012 David Anderson
7.6 + *
7.7 + * This file is part of JITCraft.
7.8 + *
7.9 + * JITCraft is free software: you can redistribute it and/or modify it under
7.10 + * the terms of the GNU General Public License as published by the Free
7.11 + * Software Foundation, either version 3 of the License, or (at your option)
7.12 + * any later version.
7.13 + *
7.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
7.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
7.17 + *
7.18 + * You should have received a copy of the GNU General Public License along with
7.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
7.20 + */
7.21 +#include "Utility.h"
7.22 +#include "Environments.h"
7.23 +#include "Structures.h"
7.24 +#include "FixedArray.h"
7.25 +#include "Zone.h"
7.26 +#include "NameBinding.h"
7.27 +
7.28 +using namespace ke;
7.29 +
7.30 +EnvironmentSlotDescriptorArray *
7.31 +EnvironmentSlotDescriptorArray::New(Zone *zone, unsigned nslots)
7.32 +{
7.33 + size_t bytesNeeded = sizeof(EnvironmentSlotDescriptorArray) +
7.34 + sizeof(EnvironmentSlotDescriptor) * nslots;
7.35 +
7.36 + Local<EnvironmentSlotDescriptorArray> array(zone);
7.37 + Local<Map> map(zone, zone->getMap(MapKind_EnvironmentSlotDescriptorArray));
7.38 +
7.39 + array = EnvironmentSlotDescriptorArray::cast(zone->allocate(map, bytesNeeded, Heap::Tenure_Old));
7.40 + if (!array)
7.41 + return NULL;
7.42 +
7.43 + // We zero the array for safety, since we could GC or fail before initialization.
7.44 + array->length_ = nslots;
7.45 + memset(array->slots(), 0, sizeof(EnvironmentSlotDescriptor) * nslots);
7.46 + return array;
7.47 +}
7.48 +
7.49 +Environment *
7.50 +Environment::New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure)
7.51 +{
7.52 + size_t bytesNeeded = sizeof(Environment) + map->structureSize();
7.53 + Local<Environment> env(zone, Environment::cast(zone->allocate(map, bytesNeeded, tenure)));
7.54 + if (!env)
7.55 + return NULL;
7.56 +
7.57 + // Initialize when called from C++, to make sure object slots are NULL.
7.58 + memset((Object *)env + 1, 0, map->structureSize());
7.59 + return env;
7.60 +}
7.61 +
7.62 +EnvironmentMap *
7.63 +EnvironmentMap::New(Zone *zone, unsigned nvars, Variable **vars)
7.64 +{
7.65 + StructureBufferBuilder structure;
7.66 +
7.67 + Local<EnvironmentSlotDescriptorArray> slots(zone);
7.68 + slots = EnvironmentSlotDescriptorArray::New(zone, nvars);
7.69 + if (!slots)
7.70 + return NULL;
7.71 +
7.72 + // Build the descriptor table, mapping each slot to an offset and type.
7.73 + Local<Type> type(zone);
7.74 + for (unsigned i = 0; i < nvars; i++) {
7.75 + assert(vars[i]->slot() == i);
7.76 + type = vars[i]->type();
7.77 +
7.78 + EnvironmentSlotDescriptor &desc = slots->slots()[i];
7.79 + if (!structure.add(type, &desc.offset))
7.80 + return NULL;
7.81 +
7.82 + desc.type = type;
7.83 + }
7.84 +
7.85 + // Allocate the actual map now.
7.86 + size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
7.87 + Local<EnvironmentMap> map(zone);
7.88 +
7.89 + map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
7.90 + if (!map)
7.91 + return NULL;
7.92 +
7.93 + // Fill in the map fields, and copy the traceable offsets structure.
7.94 + map->structureSize_ = structure.structureSize();
7.95 + map->traceOffsetCount_ = structure.traceableOffsetCount();
7.96 + map->slots_ = slots;
7.97 + memcpy(const_cast<unsigned *>(map->traceOffsets()), structure.offsets(), sizeof(unsigned) * structure.traceableOffsetCount());
7.98 +
7.99 + return map;
7.100 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/jitcraft/Environments.h Mon Jul 23 01:19:44 2012 -0700
8.3 @@ -0,0 +1,168 @@
8.4 +/*
8.5 + * Copyright (C) 2012 David Anderson
8.6 + *
8.7 + * This file is part of JITCraft.
8.8 + *
8.9 + * JITCraft is free software: you can redistribute it and/or modify it under
8.10 + * the terms of the GNU General Public License as published by the Free
8.11 + * Software Foundation, either version 3 of the License, or (at your option)
8.12 + * any later version.
8.13 + *
8.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
8.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8.17 + *
8.18 + * You should have received a copy of the GNU General Public License along with
8.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
8.20 + */
8.21 +#ifndef _include_ke_environment_h_
8.22 +#define _include_ke_environment_h_
8.23 +
8.24 +#include "Objects.h"
8.25 +#include "Handles.h"
8.26 +#include "Heap.h"
8.27 +#include "FixedArray.h"
8.28 +
8.29 +namespace ke {
8.30 +
8.31 +class EnvironmentMap;
8.32 +class Variable;
8.33 +class ByteArray;
8.34 +class Type;
8.35 +
8.36 +// An environment represents the lexical environment of a code or function
8.37 +// object. It used for variables which may be accessed outside a function's
8.38 +// normal activation (i.e., upvars).
8.39 +//
8.40 +// A module uses an Environment to store its global variables.
8.41 +class Environment : public Object
8.42 +{
8.43 + template <typename T>
8.44 + inline T *pointerToSlot(unsigned slot);
8.45 +
8.46 + public:
8.47 + static Environment *New(Zone *zone, Handle<EnvironmentMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
8.48 +
8.49 + inline EnvironmentMap *map();
8.50 + inline size_t size();
8.51 +
8.52 + float getFloat(unsigned slot) {
8.53 + return *pointerToSlot<float>(slot);
8.54 + }
8.55 + int getInt32(unsigned slot) {
8.56 + return *pointerToSlot<int>(slot);
8.57 + }
8.58 + Object *getObject(unsigned slot) {
8.59 + return *pointerToSlot<Object *>(slot);
8.60 + }
8.61 + void setFloat(unsigned slot, float f) {
8.62 + *pointerToSlot<float>(slot) = f;
8.63 + }
8.64 + void setInt32(unsigned slot, int i) {
8.65 + *pointerToSlot<int>(slot) = i;
8.66 + }
8.67 + void setObject(unsigned slot, Object *obj) {
8.68 + // :TODO: write barrier
8.69 + *pointerToSlot<Object *>(slot) = obj;
8.70 + }
8.71 +
8.72 + static inline size_t offsetOfSlotOffset(unsigned offset) {
8.73 + return sizeof(Environment) + offset;
8.74 + }
8.75 +
8.76 + static inline Environment *cast(Object *obj) {
8.77 + assert(!obj || obj->is(MapKind_Environment));
8.78 + return reinterpret_cast<Environment *>(obj);
8.79 + }
8.80 +};
8.81 +
8.82 +struct EnvironmentSlotDescriptor
8.83 +{
8.84 + Barriered<Type> type;
8.85 + unsigned offset;
8.86 +};
8.87 +
8.88 +class EnvironmentSlotDescriptorArray : public Object
8.89 +{
8.90 + unsigned length_;
8.91 +
8.92 + public:
8.93 + static EnvironmentSlotDescriptorArray *New(Zone *zone, unsigned length);
8.94 +
8.95 + EnvironmentSlotDescriptor *slots() {
8.96 + return reinterpret_cast<EnvironmentSlotDescriptor *>(this + 1);
8.97 + }
8.98 + EnvironmentSlotDescriptor &at(unsigned slot) {
8.99 + assert(slot < length_);
8.100 + return slots()[slot];
8.101 + }
8.102 + unsigned length() {
8.103 + return length_;
8.104 + }
8.105 + unsigned size() {
8.106 + return Align(sizeof(*this) + length() * sizeof(EnvironmentSlotDescriptorArray),
8.107 + kObjectAlignment);
8.108 + }
8.109 +
8.110 + static inline EnvironmentSlotDescriptorArray *cast(Object *obj) {
8.111 + assert(!obj || obj->is(MapKind_EnvironmentSlotDescriptorArray));
8.112 + return reinterpret_cast<EnvironmentSlotDescriptorArray *>(obj);
8.113 + }
8.114 +};
8.115 +
8.116 +class EnvironmentMap : public Map
8.117 +{
8.118 + unsigned structureSize_;
8.119 + unsigned traceOffsetCount_;
8.120 + Barriered<EnvironmentSlotDescriptorArray> slots_;
8.121 +
8.122 + public:
8.123 + static EnvironmentMap *New(Zone *zone, unsigned nvars, Variable **vars);
8.124 +
8.125 + unsigned structureSize() {
8.126 + return structureSize_;
8.127 + }
8.128 + unsigned traceOffsetCount() {
8.129 + return traceOffsetCount_;
8.130 + }
8.131 + const unsigned *traceOffsets() {
8.132 + return reinterpret_cast<unsigned *>(this + 1);
8.133 + }
8.134 + size_t size() {
8.135 + return Align(sizeof(EnvironmentMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
8.136 + }
8.137 + EnvironmentSlotDescriptor &slotDescriptor(unsigned slot) {
8.138 + return slots_->at(slot);
8.139 + }
8.140 +
8.141 + static inline size_t offsetOfSlots() {
8.142 + return offsetof(EnvironmentMap, slots_);
8.143 + }
8.144 +
8.145 + static inline EnvironmentMap *cast(Object *obj) {
8.146 + assert(!obj || obj->is(MapKind_MetaEnvironment));
8.147 + return reinterpret_cast<EnvironmentMap *>(obj);
8.148 + }
8.149 +};
8.150 +
8.151 +size_t
8.152 +Environment::size()
8.153 +{
8.154 + return Align(sizeof(Environment) + map()->structureSize(), kObjectAlignment);
8.155 +}
8.156 +
8.157 +EnvironmentMap *
8.158 +Environment::map()
8.159 +{
8.160 + return EnvironmentMap::cast(Object::map());
8.161 +}
8.162 +
8.163 +template <typename T> T *
8.164 +Environment::pointerToSlot(unsigned slot)
8.165 +{
8.166 + return reinterpret_cast<T *>(reinterpret_cast<char *>(this + 1) + map()->slotDescriptor(slot).offset);
8.167 +}
8.168 +
8.169 +}
8.170 +
8.171 +#endif // _include_ke_environment_h_
9.1 --- a/jitcraft/FixedArray.cpp Fri Jul 20 00:03:10 2012 -0700
9.2 +++ b/jitcraft/FixedArray.cpp Mon Jul 23 01:19:44 2012 -0700
9.3 @@ -44,7 +44,6 @@
9.4 ByteArray *
9.5 ByteArray::New(Zone *zone, unsigned length, Heap::Tenure tenure)
9.6 {
9.7 - // :TODO: error...
9.8 if (length >= kMaxFixedArrayLength) {
9.9 zone->reportError(Message_ArrayTooBig);
9.10 return NULL;
9.11 @@ -59,3 +58,19 @@
9.12 return array;
9.13 }
9.14
9.15 +ByteArray *
9.16 +ByteArray::New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure)
9.17 +{
9.18 + if (length >= kMaxFixedArrayLength) {
9.19 + zone->reportError(Message_ArrayTooBig);
9.20 + return NULL;
9.21 + }
9.22 +
9.23 + Local<ByteArray> array(zone, ByteArray::cast(zone->allocate(map, SizeFor(length), tenure)));
9.24 + if (!array)
9.25 + return NULL;
9.26 +
9.27 + array->length_ = length;
9.28 + memset(array->raw(), 0, length);
9.29 + return array;
9.30 +}
10.1 --- a/jitcraft/FixedArray.h Fri Jul 20 00:03:10 2012 -0700
10.2 +++ b/jitcraft/FixedArray.h Mon Jul 23 01:19:44 2012 -0700
10.3 @@ -65,6 +65,7 @@
10.4
10.5 public:
10.6 static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
10.7 + static ByteArray *New(Zone *zone, Handle<Map> map, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
10.8
10.9 unsigned length() {
10.10 return length_;
11.1 --- a/jitcraft/Handles.h Fri Jul 20 00:03:10 2012 -0700
11.2 +++ b/jitcraft/Handles.h Mon Jul 23 01:19:44 2012 -0700
11.3 @@ -19,6 +19,8 @@
11.4 #ifndef _include_jitcraft_rooting_h_
11.5 #define _include_jitcraft_rooting_h_
11.6
11.7 +#include <stdlib.h>
11.8 +
11.9 namespace ke {
11.10
11.11 class Zone;
11.12 @@ -67,7 +69,7 @@
11.13 private:
11.14 template <typename S>
11.15 void typeCheck() {
11.16 -#ifdef DEBUG
11.17 +#ifndef NDEBUG
11.18 T *v1 = NULL;
11.19 S *v2 = NULL;
11.20 v1 = v2;
12.1 --- a/jitcraft/Interpreter.cpp Fri Jul 20 00:03:10 2012 -0700
12.2 +++ b/jitcraft/Interpreter.cpp Mon Jul 23 01:19:44 2012 -0700
12.3 @@ -23,6 +23,7 @@
12.4 #include "Array.h"
12.5 #include "Reference.h"
12.6 #include "Strings.h"
12.7 +#include "Environments.h"
12.8 #include "Heap-inl.h"
12.9
12.10 using namespace ke;
12.11 @@ -80,11 +81,11 @@
12.12
12.13 // Generate an array with completely static sizes.
12.14 static Array *
12.15 -GenerateArray(Zone *zone, Handle<ArrayMap> map)
12.16 +GenerateArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
12.17 {
12.18 assert(map->type()->elements() != -1);
12.19
12.20 - Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), Heap::Tenure_Stack));
12.21 + Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), tenure));
12.22 if (!array)
12.23 return NULL;
12.24
12.25 @@ -94,7 +95,7 @@
12.26 Local<ArrayMap> contained(zone, map->contained());
12.27 Local<Array> sub(zone);
12.28 for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
12.29 - sub = GenerateArray(zone, contained);
12.30 + sub = GenerateArray(zone, contained, tenure);
12.31 if (!sub)
12.32 return NULL;
12.33 array->writeObject(zone, i, sub);
12.34 @@ -685,10 +686,11 @@
12.35 break;
12.36 }
12.37
12.38 -case OP_NEWARRAY_LIFO:
12.39 +case OP_NEWARRAY:
12.40 {
12.41 - Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc))));
12.42 - Array *array = GenerateArray(zone, map);
12.43 + Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
12.44 + Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
12.45 + Array *array = GenerateArray(zone, map, tenure);
12.46 if (!array)
12.47 goto error;
12.48 top.sp->obj = array;
12.49 @@ -870,6 +872,51 @@
12.50 break;
12.51 }
12.52
12.53 +case OP_GETGLOBAL_I:
12.54 +{
12.55 + unsigned slot = READ_UINT32(top.pc);
12.56 + top.sp++;
12.57 + top.sp[-1].i32 = top.fp->code()->module()->environment()->getInt32(slot);
12.58 + break;
12.59 +}
12.60 +
12.61 +case OP_GETGLOBAL_F:
12.62 +{
12.63 + unsigned slot = READ_UINT32(top.pc);
12.64 + top.sp++;
12.65 + top.sp[-1].f = top.fp->code()->module()->environment()->getFloat(slot);
12.66 + break;
12.67 +}
12.68 +
12.69 +case OP_GETGLOBAL_O:
12.70 +{
12.71 + unsigned slot = READ_UINT32(top.pc);
12.72 + top.sp++;
12.73 + top.sp[-1].obj = top.fp->code()->module()->environment()->getObject(slot);
12.74 + break;
12.75 +}
12.76 +
12.77 +case OP_SETGLOBAL_I:
12.78 +{
12.79 + unsigned slot = READ_UINT32(top.pc);
12.80 + top.fp->code()->module()->environment()->setInt32(slot, top.sp[-1].i32);
12.81 + break;
12.82 +}
12.83 +
12.84 +case OP_SETGLOBAL_F:
12.85 +{
12.86 + unsigned slot = READ_UINT32(top.pc);
12.87 + top.fp->code()->module()->environment()->setFloat(slot, top.sp[-1].f);
12.88 + break;
12.89 +}
12.90 +
12.91 +case OP_SETGLOBAL_O:
12.92 +{
12.93 + unsigned slot = READ_UINT32(top.pc);
12.94 + top.fp->code()->module()->environment()->setObject(slot, top.sp[-1].obj);
12.95 + break;
12.96 +}
12.97 +
12.98 default:
12.99 assert(false);
12.100 return false;
13.1 --- a/jitcraft/Modules.cpp Fri Jul 20 00:03:10 2012 -0700
13.2 +++ b/jitcraft/Modules.cpp Mon Jul 23 01:19:44 2012 -0700
13.3 @@ -37,6 +37,7 @@
13.4 module->file_ = NULL;
13.5 module->publics_ = NULL;
13.6 module->natives_ = NULL;
13.7 + module->environment_ = NULL;
13.8 module->nativeIdentity_ = NULL;
13.9 return module;
13.10 }
14.1 --- a/jitcraft/Modules.h Fri Jul 20 00:03:10 2012 -0700
14.2 +++ b/jitcraft/Modules.h Mon Jul 23 01:19:44 2012 -0700
14.3 @@ -24,12 +24,16 @@
14.4
14.5 namespace ke {
14.6
14.7 +class Environment;
14.8 +
14.9 class Module : public Object
14.10 {
14.11 Barriered<FixedArray> functions_;
14.12 Barriered<FixedArray> publics_;
14.13 Barriered<FixedArray> natives_;
14.14 Barriered<String> file_;
14.15 + Barriered<Environment> environment_;
14.16 + Barriered<Code> code_;
14.17 void *nativeIdentity_;
14.18
14.19 public:
14.20 @@ -53,6 +57,12 @@
14.21 String *file() {
14.22 return file_;
14.23 }
14.24 + Environment *environment() {
14.25 + return environment_;
14.26 + }
14.27 + Code *code() {
14.28 + return code_;
14.29 + }
14.30
14.31 void setPublics(Handle<FixedArray> publics) {
14.32 publics_ = publics;
14.33 @@ -63,6 +73,12 @@
14.34 void setPath(Handle<String> path) {
14.35 file_ = path;
14.36 }
14.37 + void setEnvironment(Handle<Environment> environment) {
14.38 + environment_ = environment;
14.39 + }
14.40 + void setCode(Handle<Code> code) {
14.41 + code_ = code;
14.42 + }
14.43
14.44 void *nativeIdentity() {
14.45 return nativeIdentity_;
14.46 @@ -84,6 +100,12 @@
14.47 static inline size_t offsetOfFile() {
14.48 return offsetof(Module, file_);
14.49 }
14.50 + static inline size_t offsetOfEnvironment() {
14.51 + return offsetof(Module, environment_);
14.52 + }
14.53 + static inline size_t offsetOfCode() {
14.54 + return offsetof(Module, code_);
14.55 + }
14.56 // End GC Descriptor.
14.57
14.58 static inline Module *cast(Object *obj) {
15.1 --- a/jitcraft/NameBinding.cpp Fri Jul 20 00:03:10 2012 -0700
15.2 +++ b/jitcraft/NameBinding.cpp Mon Jul 23 01:19:44 2012 -0700
15.3 @@ -18,6 +18,7 @@
15.4 #include "NameBinding.h"
15.5 #include "Strings.h"
15.6 #include "Zone.h"
15.7 +#include "Scopes.h"
15.8
15.9 using namespace ke;
15.10
15.11 @@ -42,3 +43,9 @@
15.12 location_(UNALLOCATED)
15.13 {
15.14 }
15.15 +
15.16 +bool
15.17 +Variable::needsHeapAllocation()
15.18 +{
15.19 + return scope()->kind() == Scope::GLOBAL;
15.20 +}
16.1 --- a/jitcraft/NameBinding.h Fri Jul 20 00:03:10 2012 -0700
16.2 +++ b/jitcraft/NameBinding.h Mon Jul 23 01:19:44 2012 -0700
16.3 @@ -176,7 +176,8 @@
16.4 enum Location {
16.5 UNALLOCATED,
16.6 STACK,
16.7 - PARAMETER
16.8 + PARAMETER,
16.9 + ENVIRONMENT
16.10 };
16.11
16.12 Variable(Scope *scope, Handle<String> name, const SourcePosition &pos);
16.13 @@ -198,6 +199,7 @@
16.14 assert(!unallocated());
16.15 return slot_;
16.16 }
16.17 + bool needsHeapAllocation();
16.18
16.19 private:
16.20 Location location_;
17.1 --- a/jitcraft/ObjectVisitor.h Fri Jul 20 00:03:10 2012 -0700
17.2 +++ b/jitcraft/ObjectVisitor.h Mon Jul 23 01:19:44 2012 -0700
17.3 @@ -28,6 +28,7 @@
17.4 #include "Functions.h"
17.5 #include "Array.h"
17.6 #include "Strings.h"
17.7 +#include "Environments.h"
17.8
17.9 namespace ke {
17.10
17.11 @@ -82,6 +83,8 @@
17.12 visitField(obj, Module::offsetOfPublics());
17.13 visitField(obj, Module::offsetOfNatives());
17.14 visitField(obj, Module::offsetOfFile());
17.15 + visitField(obj, Module::offsetOfEnvironment());
17.16 + visitField(obj, Module::offsetOfCode());
17.17 return sizeof(Module);
17.18 }
17.19
17.20 @@ -119,6 +122,28 @@
17.21 return sizeof(ArrayMap);
17.22 }
17.23
17.24 + size_t iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray *env) {
17.25 + unsigned length = env->length();
17.26 + EnvironmentSlotDescriptor *desc = env->slots();
17.27 + for (unsigned i = 0; i < length; i++)
17.28 + this->visit(desc->type.addr());
17.29 + return env->size();
17.30 + }
17.31 +
17.32 + size_t iterateEnvironmentMap(EnvironmentMap *map) {
17.33 + visitField(map, EnvironmentMap::offsetOfSlots());
17.34 + return map->size();
17.35 + }
17.36 +
17.37 + size_t iterateEnvironment(Environment *env) {
17.38 + EnvironmentMap *map = env->map();
17.39 + const unsigned *offsets = map->traceOffsets();
17.40 + unsigned noffsets = map->traceOffsetCount();
17.41 + for (unsigned i = 0; i < noffsets; i++)
17.42 + visitField(env, Environment::offsetOfSlotOffset(offsets[i]));
17.43 + return env->size();
17.44 + }
17.45 +
17.46 public:
17.47 size_t iterate(Object *obj) {
17.48 visitField(obj, Object::offsetOfMap());
17.49 @@ -154,12 +179,21 @@
17.50 case MapKind_Array:
17.51 return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
17.52
17.53 + case MapKind_EnvironmentSlotDescriptorArray:
17.54 + return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
17.55 +
17.56 + case MapKind_Environment:
17.57 + return iterateEnvironment(Environment::cast(obj));
17.58 +
17.59 case MapKind_Native:
17.60 return iterateNative(obj);
17.61
17.62 case MapKind_MetaArray:
17.63 return iterateArrayMap(ArrayMap::cast(obj));
17.64
17.65 + case MapKind_MetaEnvironment:
17.66 + return iterateEnvironmentMap(EnvironmentMap::cast(obj));
17.67 +
17.68 default:
17.69 assert(map->kind() == MapKind_Meta);
17.70 return sizeof(Map);
17.71 @@ -201,9 +235,18 @@
17.72 case MapKind_Array:
17.73 return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
17.74
17.75 + case MapKind_EnvironmentSlotDescriptorArray:
17.76 + return EnvironmentSlotDescriptorArray::cast(obj)->size();
17.77 +
17.78 + case MapKind_Environment:
17.79 + return Environment::cast(obj)->size();
17.80 +
17.81 case MapKind_MetaArray:
17.82 return sizeof(ArrayMap);
17.83
17.84 + case MapKind_MetaEnvironment:
17.85 + return EnvironmentMap::cast(obj)->size();
17.86 +
17.87 case MapKind_FreeRegion:
17.88 return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
17.89
18.1 --- a/jitcraft/Objects.h Fri Jul 20 00:03:10 2012 -0700
18.2 +++ b/jitcraft/Objects.h Mon Jul 23 01:19:44 2012 -0700
18.3 @@ -48,14 +48,17 @@
18.4 MapKind_String,
18.5 MapKind_Native,
18.6 MapKind_FreeRegion, // Special map denoting freed space.
18.7 + MapKind_EnvironmentSlotDescriptorArray,
18.8 + MapKind_Environment,
18.9
18.10 // Used to represent Arrays. This does not have a canonical map.
18.11 MapKind_Array,
18.12
18.13 // These represent special Map subclasses that require special tracing.
18.14 MapKinds_Special,
18.15 - MapKind_Meta, // (default map class)
18.16 - MapKind_MetaArray, // ArrayMap instances
18.17 + MapKind_Meta, // (default map class)
18.18 + MapKind_MetaArray, // ArrayMap instances
18.19 + MapKind_MetaEnvironment, // EnvironmentMap instances
18.20 MapKinds_EndSpecial,
18.21
18.22 MapKinds_Total
19.1 --- a/jitcraft/Opcodes.cpp Fri Jul 20 00:03:10 2012 -0700
19.2 +++ b/jitcraft/Opcodes.cpp Mon Jul 23 01:19:44 2012 -0700
19.3 @@ -76,7 +76,7 @@
19.4 // any other position indicates a failure to mark that position as a
19.5 // safepoint, which is a bug.
19.6 Opcode op = Opcode(*(start() + pcOffset));
19.7 - assert(op == OP_CALL || op == OP_NEWARRAY_LIFO || op == OP_VARREF_LIFO ||
19.8 + assert(op == OP_CALL || op == OP_NEWARRAY || op == OP_VARREF_LIFO ||
19.9 op == OP_ARGREF_LIFO || op == OP_SLOTREF_LIFO || op == OP_ARRAYREF_LIFO ||
19.10 op == OP_ARRAYCOPY);
19.11
19.12 @@ -238,9 +238,10 @@
19.13 fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
19.14 break;
19.15
19.16 - case OP_NEWARRAY_LIFO:
19.17 + case OP_NEWARRAY:
19.18 {
19.19 - ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
19.20 + Heap::Tenure tenure = (Heap::Tenure)pc[1];
19.21 + ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc + 1)));
19.22 fprintf(fp, "%s:", map->type()->innermost()->tag()
19.23 ? map->type()->innermost()->tag()->chars()
19.24 : "_");
19.25 @@ -248,6 +249,10 @@
19.26 Type *type = map->type();
19.27 fprintf(fp, "[%d]", type->elements());
19.28 }
19.29 + if (tenure == Heap::Tenure_Stack)
19.30 + fprintf(fp, " ; lifo");
19.31 + else if (tenure == Heap::Tenure_Old)
19.32 + fprintf(fp, " ; pretenured");
19.33 break;
19.34 }
19.35
19.36 @@ -261,6 +266,12 @@
19.37 case OP_ARGREF_LIFO:
19.38 case OP_OBJECT:
19.39 case OP_GETMODULE_FN:
19.40 + case OP_GETGLOBAL_I:
19.41 + case OP_GETGLOBAL_F:
19.42 + case OP_GETGLOBAL_O:
19.43 + case OP_SETGLOBAL_I:
19.44 + case OP_SETGLOBAL_F:
19.45 + case OP_SETGLOBAL_O:
19.46 fprintf(fp, "%u", READ_UINT32(pc));
19.47 break;
19.48
20.1 --- a/jitcraft/Opcodes.tbl Fri Jul 20 00:03:10 2012 -0700
20.2 +++ b/jitcraft/Opcodes.tbl Mon Jul 23 01:19:44 2012 -0700
20.3 @@ -116,12 +116,12 @@
20.4 OPDEF(OP_SETARRAY_C, 45, "setarray.c", 1, 3, 1)
20.5 OPDEF(OP_GETARRAY_O, 46, "getarray.o", 1, 2, 1)
20.6
20.7 -// Allocate an array, info LIFO space if possible. The ArrayMap to use is
20.8 -// specified as an index into the script's Map table.
20.9 +// Allocate an array. The HeapTenure is stored as a byte following pc. The
20.10 +// ArrayMap to use is specified as an index into the script's Map table.
20.11 //
20.12 // Format:
20.13 // [u8 op] [u32 index]
20.14 -OPDEF(OP_NEWARRAY_LIFO, 47, "newarray.lifo", 5, 0, 1)
20.15 +OPDEF(OP_NEWARRAY, 47, "newarray", 6, 0, 1)
20.16
20.17 // Performs a bounds check on an unsafe array.
20.18 //
20.19 @@ -236,3 +236,11 @@
20.20 // Loads a function from a module object. The operand is the slot number
20.21 // in the module.
20.22 OPDEF(OP_GETMODULE_FN, 92, "getmodule.fn", 5, 1, 1)
20.23 +
20.24 +// Opcodes for accessing an environment slot in the global scope.
20.25 +OPDEF(OP_SETGLOBAL_I, 93, "setglobal.i", 5, 1, 1)
20.26 +OPDEF(OP_SETGLOBAL_F, 94, "setglobal.f", 5, 1, 1)
20.27 +OPDEF(OP_SETGLOBAL_O, 95, "setglobal.o", 5, 1, 1)
20.28 +OPDEF(OP_GETGLOBAL_I, 96, "getglobal.i", 5, 0, 1)
20.29 +OPDEF(OP_GETGLOBAL_F, 97, "getglobal.f", 5, 0, 1)
20.30 +OPDEF(OP_GETGLOBAL_O, 98, "getglobal.o", 5, 0, 1)
20.31 \ No newline at end of file
21.1 --- a/jitcraft/Parser.cpp Fri Jul 20 00:03:10 2012 -0700
21.2 +++ b/jitcraft/Parser.cpp Mon Jul 23 01:19:44 2012 -0700
21.3 @@ -1076,14 +1076,14 @@
21.4 break;
21.5 }
21.6
21.7 - // case TOK_NEW:
21.8 - // {
21.9 - // if ((statement = variableDeclaration()) == NULL)
21.10 - // return NULL;
21.11 - // if (!matchSemicolon())
21.12 - // return NULL;
21.13 - // break;
21.14 - // }
21.15 + case TOK_NEW:
21.16 + {
21.17 + if ((statement = variableDeclaration()) == NULL)
21.18 + return NULL;
21.19 + if (!matchSemicolon())
21.20 + return NULL;
21.21 + break;
21.22 + }
21.23
21.24 case TOK_ENUM:
21.25 if ((statement = enum_()) == NULL)
22.1 --- a/jitcraft/Scopes.cpp Fri Jul 20 00:03:10 2012 -0700
22.2 +++ b/jitcraft/Scopes.cpp Mon Jul 23 01:19:44 2012 -0700
22.3 @@ -22,6 +22,7 @@
22.4 #include "TypeManager.h"
22.5 #include "Strings.h"
22.6 #include "CompileContext.h"
22.7 +#include "Environments.h"
22.8
22.9 using namespace ke;
22.10
22.11 @@ -152,6 +153,7 @@
22.12 children_[i]->allocate();
22.13 }
22.14
22.15 + Local<Type> type(ZONE());
22.16 for (size_t i = 0; i < names_.length(); i++) {
22.17 BoundName *name = names_[i];
22.18
22.19 @@ -161,6 +163,8 @@
22.20 fun->allocate(numNatives_++);
22.21 else
22.22 fun->allocate(numFunctions_++);
22.23 + } else if (name->kind() == BoundName::VARIABLE) {
22.24 + allocate(name->toVariable());
22.25 }
22.26 }
22.27 }
22.28 @@ -171,8 +175,13 @@
22.29 if (!var->unallocated())
22.30 return;
22.31
22.32 - var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
22.33 - locals_++;
22.34 + if (kind() == GLOBAL) {
22.35 + var->allocate(Variable::ENVIRONMENT, envVars_.length());
22.36 + envVars_.append(var);
22.37 + } else {
22.38 + var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
22.39 + locals_++;
22.40 + }
22.41 }
22.42
22.43 void
22.44 @@ -256,3 +265,9 @@
22.45 lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
22.46 lifoSlot_->setType(type);
22.47 }
22.48 +
22.49 +EnvironmentMap *
22.50 +Scope::createEnvironmentMap(Zone *zone)
22.51 +{
22.52 + return EnvironmentMap::New(zone, envVars_.length(), envVars_.buffer());
22.53 +}
23.1 --- a/jitcraft/Scopes.h Fri Jul 20 00:03:10 2012 -0700
23.2 +++ b/jitcraft/Scopes.h Mon Jul 23 01:19:44 2012 -0700
23.3 @@ -21,10 +21,12 @@
23.4 #include "PoolAllocator.h"
23.5 #include "AST.h"
23.6 #include "NameBinding.h"
23.7 +#include "Structures.h"
23.8
23.9 namespace ke {
23.10
23.11 class CompileContext;
23.12 +class EnvironmentMap;
23.13
23.14 class Scope : public PoolObject
23.15 {
23.16 @@ -36,6 +38,7 @@
23.17 unsigned maxContainedLocals_;
23.18 unsigned numFunctions_;
23.19 unsigned numNatives_;
23.20 + PoolList<Variable *> envVars_;
23.21 Variable *lifoSlot_;
23.22
23.23 bool empty() const {
23.24 @@ -75,6 +78,9 @@
23.25 unsigned numArguments() const {
23.26 return parameters_.length();
23.27 }
23.28 + unsigned numEnvironmentVars() const {
23.29 + return envVars_.length();
23.30 + }
23.31 Variable *getArgument(size_t index) {
23.32 return parameters_[index];
23.33 }
23.34 @@ -93,6 +99,8 @@
23.35 NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
23.36 NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
23.37
23.38 + EnvironmentMap *createEnvironmentMap(Zone *zone);
23.39 +
23.40 void allocate(Variable *var);
23.41 void allocate();
23.42 void allocateGlobals();
24.1 --- a/jitcraft/SemanticAnalysis.cpp Fri Jul 20 00:03:10 2012 -0700
24.2 +++ b/jitcraft/SemanticAnalysis.cpp Mon Jul 23 01:19:44 2012 -0700
24.3 @@ -21,6 +21,7 @@
24.4 #include "Zone.h"
24.5 #include "TypeManager.h"
24.6 #include "Scopes.h"
24.7 +#include "NameBinding.h"
24.8 #include "Heap-inl.h"
24.9 #include "Strings.h"
24.10
24.11 @@ -111,6 +112,8 @@
24.12 if (cc_.failures())
24.13 return false;
24.14
24.15 + scope_ = tree_->scope();
24.16 +
24.17 for (size_t i = 0; i < tree_->statements()->length(); i++) {
24.18 Statement *statement = tree_->statements()->at(i);
24.19 if (statement->isFunctionStatement()) {
24.20 @@ -609,10 +612,11 @@
24.21 check = check->contained();
24.22 }
24.23
24.24 - // Right now, any array is allowed on the LIFO heap. In case the
24.25 - // runtime actually decides to use the LIFO heap, we must reserve
24.26 - // a slot so we can unwind the heap when the current scope leaves.
24.27 - scope_->setUsesLifoHeap();
24.28 + // If this variable is stack allocated, we could use the LIFO heap
24.29 + // to allocate it. If that's the case, make sure to reserve a slot
24.30 + // so we can unwind the LIFO heap at the end of this scope.
24.31 + if (!node->variable()->needsHeapAllocation())
24.32 + scope_->setUsesLifoHeap();
24.33 } else {
24.34 if (node->initialization()) {
24.35 Local<Type> right(zone_, visitForLoad(node->initialization()));
24.36 @@ -850,7 +854,7 @@
24.37 if (given->primitive() != actual->primitive()) {
24.38 // :TODO: leaks an interior pointer
24.39 const char *givenTag = given->tag() ? given->tag()->chars() : "_";
24.40 - const char *actualTag = given->tag() ? given->tag()->chars() : "_";
24.41 + const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
24.42 cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
24.43 return false;
24.44 }
25.1 --- a/jitcraft/Stack.cpp Fri Jul 20 00:03:10 2012 -0700
25.2 +++ b/jitcraft/Stack.cpp Mon Jul 23 01:19:44 2012 -0700
25.3 @@ -95,6 +95,29 @@
25.4 }
25.5
25.6 bool
25.7 +Stack::pushModuleFrame(Handle<Module> module, InvokeArgs &args)
25.8 +{
25.9 + size_t nbytes = SizeForCodeFrame(module->code());
25.10 + if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
25.11 + assert(false);
25.12 + return false;
25.13 + }
25.14 +
25.15 + args.args_ = top_.sp;
25.16 + args.nargs_ = 0;
25.17 + args.stack_ = this;
25.18 +
25.19 + Frame *frame = reinterpret_cast<Frame *>(top_.sp);
25.20 + new (frame) Frame(top_.fp, top_.pc, NULL, module->code(), zone_->heap().lifoPosition());
25.21 +
25.22 + top_.pc = frame->code()->start();
25.23 + top_.sp = frame->stackBase();
25.24 + top_.fp = frame;
25.25 +
25.26 + return true;
25.27 +}
25.28 +
25.29 +bool
25.30 Stack::pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc)
25.31 {
25.32 size_t nbytes = sizeof(intptr_t) * argc + sizeof(Frame);
26.1 --- a/jitcraft/Stack.h Fri Jul 20 00:03:10 2012 -0700
26.2 +++ b/jitcraft/Stack.h Mon Jul 23 01:19:44 2012 -0700
26.3 @@ -193,6 +193,7 @@
26.4 Frame *popInlineFrame();
26.5
26.6 bool pushInvokeFrame(Handle<Function> fun, InvokeArgs &args);
26.7 + bool pushModuleFrame(Handle<Module> module, InvokeArgs &args);
26.8 bool pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc);
26.9
26.10 Top *top() {
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/jitcraft/Structures.cpp Mon Jul 23 01:19:44 2012 -0700
27.3 @@ -0,0 +1,46 @@
27.4 +/* vim: set ts=4 sw=4 tw=99 et
27.5 + *
27.6 + * Copyright (C) 2012 David Anderson
27.7 + *
27.8 + * This file is part of JITCraft.
27.9 + *
27.10 + * JITCraft is free software: you can redistribute it and/or modify it under
27.11 + * the terms of the GNU General Public License as published by the Free
27.12 + * Software Foundation, either version 3 of the License, or (at your option)
27.13 + * any later version.
27.14 + *
27.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
27.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
27.18 + *
27.19 + * You should have received a copy of the GNU General Public License along with
27.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
27.21 + */
27.22 +#include "Structures.h"
27.23 +#include "Types.h"
27.24 +
27.25 +using namespace ke;
27.26 +
27.27 +StructureBufferBuilder::StructureBufferBuilder()
27.28 + : size_(0)
27.29 +{
27.30 +}
27.31 +
27.32 +bool
27.33 +StructureBufferBuilder::add(Handle<Type> type, unsigned *offset)
27.34 +{
27.35 + *offset = size_;
27.36 +
27.37 + if (!type->isTraceable()) {
27.38 + // For now, assume the size of primitives is 4-byte.
27.39 + assert(type->isInt32() || type->isFloat());
27.40 + size_ += 4;
27.41 + return true;
27.42 + }
27.43 +
27.44 + if (!offsets_.append(size_))
27.45 + return false;
27.46 +
27.47 + size_ += sizeof(Object *);
27.48 + return true;
27.49 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/jitcraft/Structures.h Mon Jul 23 01:19:44 2012 -0700
28.3 @@ -0,0 +1,60 @@
28.4 +/* vim: set ts=4 sw=4 tw=99 et
28.5 + *
28.6 + * Copyright (C) 2012 David Anderson
28.7 + *
28.8 + * This file is part of JITCraft.
28.9 + *
28.10 + * JITCraft is free software: you can redistribute it and/or modify it under
28.11 + * the terms of the GNU General Public License as published by the Free
28.12 + * Software Foundation, either version 3 of the License, or (at your option)
28.13 + * any later version.
28.14 + *
28.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
28.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
28.18 + *
28.19 + * You should have received a copy of the GNU General Public License along with
28.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
28.21 + */
28.22 +#ifndef _include_jc_structure_h_
28.23 +#define _include_jc_structure_h_
28.24 +
28.25 +#include "Objects.h"
28.26 +#include "Handles.h"
28.27 +#include "Vector.h"
28.28 +
28.29 +namespace ke {
28.30 +
28.31 +class Type;
28.32 +class String;
28.33 +class FixedArray;
28.34 +
28.35 +// When describing composite structures, the GC must be able to trace interior
28.36 +// references to Objects. To make this possible, maps that describe composite
28.37 +// structures must provide a list of offsets into their objects that are
28.38 +// traceable. StructureBufferBuilder assists with this.
28.39 +class StructureBufferBuilder
28.40 +{
28.41 + public:
28.42 + StructureBufferBuilder();
28.43 +
28.44 + bool add(Handle<Type> type, unsigned *offset);
28.45 +
28.46 + unsigned structureSize() const {
28.47 + return size_;
28.48 + }
28.49 + unsigned traceableOffsetCount() const {
28.50 + return offsets_.length();
28.51 + }
28.52 + const unsigned *offsets() {
28.53 + return offsets_.buffer();
28.54 + }
28.55 +
28.56 + private:
28.57 + Vector<unsigned> offsets_;
28.58 + unsigned size_;
28.59 +};
28.60 +
28.61 +}
28.62 +
28.63 +#endif // _include_jc_structure_h_
29.1 --- a/jitcraft/Vector.h Fri Jul 20 00:03:10 2012 -0700
29.2 +++ b/jitcraft/Vector.h Mon Jul 23 01:19:44 2012 -0700
29.3 @@ -26,7 +26,7 @@
29.4
29.5 namespace ke {
29.6
29.7 -template <typename T, typename AllocPolicy = NormalAllocPolicy>
29.8 +template <typename T, typename AllocPolicy = ZoneAllocatorPolicy>
29.9 class Vector : public AllocPolicy
29.10 {
29.11 public:
30.1 --- a/jitcraft/Zone.cpp Fri Jul 20 00:03:10 2012 -0700
30.2 +++ b/jitcraft/Zone.cpp Mon Jul 23 01:19:44 2012 -0700
30.3 @@ -76,6 +76,8 @@
30.4 return false;
30.5 if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
30.6 return false;
30.7 + if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
30.8 + return false;
30.9 if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)
30.10 return false;
30.11 if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
30.12 @@ -86,6 +88,11 @@
30.13 return false;
30.14 if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
30.15 return false;
30.16 + if ((maps_[MapKind_EnvironmentSlotDescriptorArray] =
30.17 + allocateMap(MapKind_EnvironmentSlotDescriptorArray, sizeof(Map))) == NULL)
30.18 + {
30.19 + return false;
30.20 + }
30.21
30.22 types_ = new TypeManager(this);
30.23 if (!types_ || !types_->initialize())
31.1 --- a/jitcraft/jitcraft.vcxproj Fri Jul 20 00:03:10 2012 -0700
31.2 +++ b/jitcraft/jitcraft.vcxproj Mon Jul 23 01:19:44 2012 -0700
31.3 @@ -99,6 +99,7 @@
31.4 <ClCompile Include="BytecodeCompiler.cpp" />
31.5 <ClCompile Include="BytecodeEmitter.cpp" />
31.6 <ClCompile Include="CompileContext.cpp" />
31.7 + <ClCompile Include="Environments.cpp" />
31.8 <ClCompile Include="Exception.cpp" />
31.9 <ClCompile Include="FixedArray.cpp" />
31.10 <ClCompile Include="Functions.cpp" />
31.11 @@ -121,6 +122,7 @@
31.12 <ClCompile Include="Stack.cpp" />
31.13 <ClCompile Include="StringPool.cpp" />
31.14 <ClCompile Include="Strings.cpp" />
31.15 + <ClCompile Include="Structures.cpp" />
31.16 <ClCompile Include="TypeManager.cpp" />
31.17 <ClCompile Include="Types.cpp" />
31.18 <ClCompile Include="Zone.cpp" />
31.19 @@ -136,6 +138,7 @@
31.20 <ClInclude Include="BytecodeCompiler.h" />
31.21 <ClInclude Include="CompactBuffer.h" />
31.22 <ClInclude Include="CompileContext.h" />
31.23 + <ClInclude Include="Environments.h" />
31.24 <ClInclude Include="FixedArray.h" />
31.25 <ClInclude Include="Functions.h" />
31.26 <ClInclude Include="GlobalRoots.h" />
31.27 @@ -166,7 +169,7 @@
31.28 <ClInclude Include="Stack.h" />
31.29 <ClInclude Include="Strings.h" />
31.30 <ClInclude Include="StringPool.h" />
31.31 - <ClInclude Include="Structure.h" />
31.32 + <ClInclude Include="Structures.h" />
31.33 <ClInclude Include="TypeManager.h" />
31.34 <ClInclude Include="Types.h" />
31.35 <ClInclude Include="Vector.h" />
32.1 --- a/jitcraft/main.cpp Fri Jul 20 00:03:10 2012 -0700
32.2 +++ b/jitcraft/main.cpp Mon Jul 23 01:19:44 2012 -0700
32.3 @@ -118,9 +118,9 @@
32.4 if (!module)
32.5 return 1;
32.6
32.7 - Ke::Local<Ke::Native> native = module->getNative(0);
32.8 - native->bind(reinterpret_cast<void *>(PrintToServer));
32.9 - module->setNativeIdentity(reinterpret_cast<void *>(5));
32.10 + //Ke::Local<Ke::Native> native = module->getNative(0);
32.11 + //native->bind(reinterpret_cast<void *>(PrintToServer));
32.12 + //module->setNativeIdentity(reinterpret_cast<void *>(5));
32.13
32.14 int result;
32.15 Ke::Local<Ke::Function> fun = module->getPublic(0);