Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ traces
/tests/streams/*.txt
npm-debug.log*
/.metadata
.DS_Store
/SOMns.iml
/libs/black-diamonds
10 changes: 10 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -529,4 +529,14 @@ kernel: ${kernel}</echo>

<move file="${svm.dir}/som-native" todir="${src.dir}/../" />
</target>

<target name="intellijinit" depends="source">
<exec executable="${mx.cmd}" dir="${svm.dir}" failonerror="true">
<env key="JAVA_HOME" value="${jvmci.home}" />
<arg value="--dynamicimports"/>
<arg value="../truffle,../tools,../compiler,../sdk"/>
<arg value="intellijinit"/>
</exec>
</target>

</project>
13 changes: 13 additions & 0 deletions src/som/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ public void setupInstruments(final Env env) {
: "Currently, CandidateIdentifer and Snapshots are not compatible";
structuralProbe = SnapshotBackend.getProbe();
}

structuralProbe = new StructuralProbe<>();
}

public SClass loadExtensionModule(final String filename) {
Expand All @@ -419,6 +421,13 @@ public MixinDefinition loadModule(final String filename) throws IOException {
return objectSystem.loadModule(filename);
}

public MixinDefinition loadModule(final String filename,MixinDefinition oldModule) throws IOException {
if (oldModule == null) {
return objectSystem.loadModule(filename);
}
return objectSystem.reLoadModule(filename,oldModule);
}

public MixinDefinition loadModule(final Source source) throws IOException {
return objectSystem.loadModule(source);
}
Expand All @@ -443,4 +452,8 @@ public static void resetClassReferences(final boolean callFromUnitTest) {

ChannelPrimitives.resetClassReferences();
}

public StructuralProbe<SSymbol, MixinDefinition, SInvokable, SlotDefinition, Variable> getStructuralProbe(){
return structuralProbe;
}
}
29 changes: 28 additions & 1 deletion src/som/compiler/MixinBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,29 @@ public MixinBuilder(final ScopeBuilder<?> outer, final AccessModifier accessModi
this.structuralProbe = structuralProbe;
}

public MixinBuilder(final ScopeBuilder<?> outer, final AccessModifier accessModifier,
final SSymbol name, final SourceSection nameSection,
final StructuralProbe<SSymbol, MixinDefinition, SInvokable, SlotDefinition, Variable> structuralProbe,
final SomLanguage language, final MixinDefinitionId mixinId){
super(outer, outer == null ? null : outer.getScope());
this.name = name;
this.nameSection = nameSection;
this.mixinId = mixinId;

this.classSide = false;
this.language = language;

this.classScope = createScope(scope);

this.initializer = new MethodBuilder(this, structuralProbe);
this.primaryFactoryMethod =
new MethodBuilder(this, classScope, false, language, structuralProbe);
this.superclassAndMixinResolutionBuilder = createSuperclassResolutionBuilder();

this.accessModifier = accessModifier;
this.structuralProbe = structuralProbe;
}

public static class MixinDefinitionError extends SemanticDefinitionError {
private static final long serialVersionUID = 5030639383869198851L;

Expand Down Expand Up @@ -493,7 +516,7 @@ protected boolean isImmutable() {
return true;
}

private void setHolders(final MixinDefinition clsDef) {
public void setHolders(final MixinDefinition clsDef) {
assert clsDef != null;
for (Dispatchable disp : dispatchables.getValues()) {
if (disp instanceof SInvokable) {
Expand Down Expand Up @@ -675,6 +698,10 @@ public void addNestedMixin(final MixinDefinition nestedMixin)
slots.put(name, cacheSlot);
}

public void addSlotsUnsafe(EconomicMap<SSymbol, SlotDefinition> newSlots){
slots.putAll(newSlots);
}

public MixinDefinitionId getMixinId() {
return mixinId;
}
Expand Down
3 changes: 2 additions & 1 deletion src/som/compiler/MixinDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ protected static boolean sameClassConstruction(final Object a, final Object b) {
return sameClassConstruction(aC.getSuperClass(), bC.getSuperClass());
}

private final ArrayList<ClassFactory> cache = new ArrayList<>(2);
public final ArrayList<ClassFactory> cache = new ArrayList<>(2);

private ClassFactory getCached(final Object superclassAndMixins) {
if (superclassAndMixins == null) {
Expand Down Expand Up @@ -907,4 +907,5 @@ public SSymbol getIdentifier() {

return identifier;
}

}
46 changes: 46 additions & 0 deletions src/som/compiler/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@ public MixinBuilder moduleDeclaration() throws ProgramDefinitionError {
return classDeclaration(null, AccessModifier.PUBLIC);
}

public MixinBuilder moduleDeclaration(MixinBuilder.MixinDefinitionId mixinDefinitionId) throws ProgramDefinitionError {
compatibilityNewspeakVersionAndFileCategory();

comments();
return classDeclaration(null, AccessModifier.PUBLIC, mixinDefinitionId);
}

protected String className() throws ParseError {
String mixinName = text;
expect(Identifier, IdentifierTag.class);
Expand Down Expand Up @@ -380,6 +387,45 @@ private MixinBuilder classDeclaration(final MixinBuilder outerBuilder,
return mxnBuilder;
}

private MixinBuilder classDeclaration(final MixinBuilder outerBuilder,
final AccessModifier accessModifier, MixinBuilder.MixinDefinitionId mixinDefinitionId) throws ProgramDefinitionError {
expectIdentifier("class", "Found unexpected token %(found)s. " +
"Tried parsing a class declaration and expected 'class' instead.",
KeywordTag.class);

int coord = getStartIndex();
String mixinName = className();
SourceSection nameSS = getSource(coord);

MixinBuilder mxnBuilder = new MixinBuilder(outerBuilder, accessModifier,
symbolFor(mixinName), nameSS, structuralProbe, language,mixinDefinitionId);

MethodBuilder primaryFactory = mxnBuilder.getPrimaryFactoryMethodBuilder();
coord = getStartIndex();

// Newspeak-spec: this is not strictly sufficient for Newspeak
// it could also parse a binary selector here, I think
// but, doesn't seem so useful, so, let's keep it simple
if (sym == Identifier || sym == Keyword) {
messagePattern(primaryFactory);
} else {
// in the standard case, the primary factory method is #new
primaryFactory.addArgument(Symbols.SELF, getEmptySource());
primaryFactory.setSignature(Symbols.NEW);
}
mxnBuilder.setupInitializerBasedOnPrimaryFactory(getSource(coord));

comments();

expect(Equal, "Unexpected symbol %(found)s."
+ " Tried to parse the class declaration of " + mixinName
+ " and expect '=' before the (optional) inheritance declaration.",
KeywordTag.class);

inheritanceListAndOrBody(mxnBuilder);
return mxnBuilder;
}

private void inheritanceListAndOrBody(final MixinBuilder mxnBuilder)
throws ProgramDefinitionError {
if (sym == NewTerm) {
Expand Down
17 changes: 17 additions & 0 deletions src/som/compiler/SourcecodeCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,21 @@ protected final MixinDefinition compile(final Parser parser,
language.getVM().reportLoadedSource(source);
return result;
}

public MixinDefinition recompileModule(Source source, StructuralProbe<SSymbol, MixinDefinition, SInvokable, SlotDefinition, Variable> structuralProbe) throws ProgramDefinitionError {
Parser parser = new Parser(source.getCharacters().toString(), source, null, language);
int coord = parser.getStartIndex();
MixinBuilder mxnBuilder = parser.moduleDeclaration();
MixinDefinition result = mxnBuilder.assemble(parser.getSource(coord));
return result;
}

public MixinDefinition recompileModule(Source source, StructuralProbe<SSymbol, MixinDefinition, SInvokable, SlotDefinition, Variable> structuralProbe, MixinDefinition oldModule) throws ProgramDefinitionError {
Parser parser = new Parser(source.getCharacters().toString(), source, null, language);
int coord = parser.getStartIndex();
MixinBuilder mxnBuilder = parser.moduleDeclaration(oldModule.getMixinId());
//mxnBuilder.addSlotsUnsafe(oldModule.getSlots());
MixinDefinition result = mxnBuilder.assemble(parser.getSource(coord));
return result;
}
}
3 changes: 3 additions & 0 deletions src/som/interpreter/nodes/dispatch/ClassSlotAccessNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ public SClass read(final SObject rcvr) {
if (cachedValue == Nil.nilObject) {
return instantiateAndWriteUnsynced(rcvr);
} else {
if (cachedValue == null) {
return instantiateAndWriteUnsynced(rcvr);
}
assert cachedValue instanceof SClass;
return (SClass) cachedValue;
}
Expand Down
30 changes: 30 additions & 0 deletions src/som/interpreter/nodes/dispatch/DispatchGuard.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package som.interpreter.nodes.dispatch;

import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.TruffleRuntime;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;

import som.compiler.MixinDefinition.SlotDefinition;
Expand All @@ -14,6 +18,15 @@


public abstract class DispatchGuard {

@CompilerDirectives.CompilationFinal
private static Assumption noModuleReloaded = Truffle.getRuntime().createAssumption("noMoRel");

public static void invalidateAssumption() {
noModuleReloaded.invalidate();
noModuleReloaded = Truffle.getRuntime().createAssumption("noMoRel");
}

public abstract boolean entryMatches(Object obj)
throws InvalidAssumptionException;

Expand Down Expand Up @@ -58,41 +71,53 @@ public static CheckSObject createSObjectCheck(final SObject obj) {
private static final class CheckClass extends DispatchGuard {

private final Class<?> expected;
private final Assumption noLoad = noModuleReloaded;

CheckClass(final Class<?> expectedClass) {
this.expected = expectedClass;
}

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
return obj.getClass() == expected;
}
}

private static final class CheckTrue extends DispatchGuard {

private final Assumption noLoad = noModuleReloaded;

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
return obj == Boolean.TRUE;
}
}

private static final class CheckFalse extends DispatchGuard {

private final Assumption noLoad = noModuleReloaded;

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
return obj == Boolean.FALSE;
}
}

private static final class CheckObjectWithoutFields extends DispatchGuard {

private final ClassFactory expected;
private final Assumption noLoad = noModuleReloaded;

CheckObjectWithoutFields(final ClassFactory expected) {
this.expected = expected;
}

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
return obj instanceof SObjectWithoutFields &&
((SObjectWithoutFields) obj).getFactory() == expected;
}
Expand All @@ -101,20 +126,23 @@ public boolean entryMatches(final Object obj) throws InvalidAssumptionException
private static final class CheckSClass extends DispatchGuard {

private final ClassFactory expected;
private final Assumption noLoad = noModuleReloaded;

CheckSClass(final ClassFactory expected) {
this.expected = expected;
}

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
return obj instanceof SClass &&
((SClass) obj).getFactory() == expected;
}
}

public abstract static class CheckSObject extends DispatchGuard {
protected final ObjectLayout expected;
protected final Assumption noLoad = noModuleReloaded;

CheckSObject(final ObjectLayout expected) {
this.expected = expected;
Expand All @@ -136,6 +164,7 @@ private static final class CheckSMutableObject extends CheckSObject {

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
expected.checkIsLatest();
return obj instanceof SMutableObject &&
((SMutableObject) obj).getObjectLayout() == expected;
Expand All @@ -155,6 +184,7 @@ private static final class CheckSImmutableObject extends CheckSObject {

@Override
public boolean entryMatches(final Object obj) throws InvalidAssumptionException {
noLoad.check();
expected.checkIsLatest();
return obj instanceof SImmutableObject &&
((SImmutableObject) obj).getObjectLayout() == expected;
Expand Down
2 changes: 1 addition & 1 deletion src/som/interpreter/objectstorage/ClassFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public final class ClassFactory {
private final MixinDefinition mixinDef;

private final EconomicSet<SlotDefinition> instanceSlots;
private final EconomicMap<SSymbol, Dispatchable> dispatchables;
public final EconomicMap<SSymbol, Dispatchable> dispatchables;

private final boolean hasOnlyImmutableFields;

Expand Down
6 changes: 5 additions & 1 deletion src/som/interpreter/objectstorage/StorageLocation.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,20 @@ public static StorageLocation createForObject(final ObjectLayout layout,
}

protected final ObjectLayout layout;
protected final SlotDefinition slot;
protected SlotDefinition slot;

protected StorageLocation(final ObjectLayout layout, final SlotDefinition slot) {
this.layout = layout;
this.slot = slot;
}


public SlotDefinition getSlot() {
return slot;
}
public void setSlot(SlotDefinition slot) {
this.slot = slot;
}

/**
* @return true, if it is an object location, false otherwise.
Expand Down
Loading