Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 1 deletion backend-v2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ set(BACKEND_SOURCES
codegen/ops/InstanceCallNode.cpp
codegen/ops/HostInteropNode.cpp
codegen/ops/NewNode.cpp
codegen/ops/IsInstanceNode.cpp)
codegen/ops/IsInstanceNode.cpp
codegen/ops/ThrowNode.cpp)

add_subdirectory(runtime)

Expand Down
38 changes: 33 additions & 5 deletions backend-v2/bridge/Exceptions.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "Exceptions.h"
#include "../runtime/Exception.h"
#include "bytecode.pb.h"
#include "runtime/ObjectProto.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/ObjectFile.h"
Expand Down Expand Up @@ -664,11 +666,9 @@ void throwInternalInconsistencyException(const std::string &errorMessage) {
RT_boxPtr(::String_createDynamicStr(errorMessage.c_str())), RT_boxNil());
}

extern "C" void
throwInternalInconsistencyException_C(const char *errorMessage) {
throw rt::LanguageException(
"InternalInconsistencyException",
RT_boxPtr(::String_createDynamicStr(errorMessage)), RT_boxNil());
extern "C" void throwInternalInconsistencyException_C(String *errorMessage) {
throw rt::LanguageException("InternalInconsistencyException",
RT_boxPtr(errorMessage), RT_boxNil());
}

extern "C" [[noreturn]] void
Expand Down Expand Up @@ -759,4 +759,32 @@ void throwCodeGenerationException(
throwCodeGenerationException(errorMessage, node.form(), file, line, column);
}

extern "C" String *exceptionToString_C(void *exception) {
rt::LanguageException *ex = (rt::LanguageException *)exception;
auto str = getExceptionString(*ex, StackTraceMode::Friendly, true);
return ::String_createDynamicStr(str.c_str());
}

extern "C" void *createException_C(const char *className, String *message,
RTValue payload) {
return new rt::LanguageException(className, RT_boxPtr(message), payload);
}

extern "C" [[noreturn]] void throwException_C(RTValue exceptionBoxed) {
if (getType(exceptionBoxed) != exceptionType) {
release(exceptionBoxed);
throwInternalInconsistencyException(
"throwException_C called with non-exception object");
}
Exception *ex = (Exception *)RT_unboxPtr(exceptionBoxed);
rt::LanguageException *le = (rt::LanguageException *)ex->bridgedData;
rt::LanguageException toThrow = *le;
release(exceptionBoxed);
throw toThrow;
}

extern "C" void deleteException_C(void *exception) {
delete (rt::LanguageException *)exception;
}

} // namespace rt
6 changes: 6 additions & 0 deletions backend-v2/bridge/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,10 @@ extern "C" [[noreturn]] void
throwNoMatchingOverloadException_C(const char *className,
const char *methodName);

extern "C" String *exceptionToString_C(void *exception);
extern "C" void *createException_C(const char *className, String *message,
RTValue payload);
extern "C" [[noreturn]] void throwException_C(RTValue exceptionBoxed);
extern "C" void deleteException_C(void *exception);

#endif
16 changes: 9 additions & 7 deletions backend-v2/codegen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,9 @@ TypedValue CodeGen::codegen(const Node &node,
return codegen(node, node.subnode().staticfield(), typeRestrictions);
case opTheVar:
return codegen(node, node.subnode().thevar(), typeRestrictions);
// case opThrow:
// return codegen(node, node.subnode().throw_(), typeRestrictions);
// case opTry:
case opThrow:
return this->codegen(node, static_cast<const clojure::rt::protobuf::bytecode::ThrowNode &>(node.subnode().throw_()), typeRestrictions);
case opTry:
// return codegen(node, node.subnode().try_(), typeRestrictions);
case opVar:
return codegen(node, node.subnode().var(), typeRestrictions);
Expand Down Expand Up @@ -379,9 +379,9 @@ ObjectTypeSet CodeGen::getType(const Node &node,
return getType(node, node.subnode().staticfield(), typeRestrictions);
case opTheVar:
return getType(node, node.subnode().thevar(), typeRestrictions);
// case opThrow:
// return getType(node, node.subnode().throw_(), typeRestrictions);
// case opTry:
case opThrow:
return this->getType(node, static_cast<const clojure::rt::protobuf::bytecode::ThrowNode &>(node.subnode().throw_()), typeRestrictions);
case opTry:
// return getType(node, node.subnode().try_(), typeRestrictions);
case opVar:
return getType(node, node.subnode().var(), typeRestrictions);
Expand Down Expand Up @@ -492,8 +492,10 @@ bool CodeGen::canThrow(const Node &node) {
case opHostInterop:
return true;

case opThrow:
case opInvoke:
return true;
default:
// Safer to assume it can throw if we don't know the node type
return true;
}
}
Expand Down
4 changes: 4 additions & 0 deletions backend-v2/codegen/CodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ class CodeGen {
const ObjectTypeSet &typeRestrictions);
TypedValue codegen(const Node &node, const IsInstanceNode &subnode,
const ObjectTypeSet &typeRestrictions);
TypedValue codegen(const Node &node, const ThrowNode &subnode,
const ObjectTypeSet &typeRestrictions);

ObjectTypeSet getType(const Node &node,
const ObjectTypeSet &typeRestrictions);
Expand Down Expand Up @@ -182,6 +184,8 @@ class CodeGen {
const ObjectTypeSet &typeRestrictions);
ObjectTypeSet getType(const Node &node, const IsInstanceNode &subnode,
const ObjectTypeSet &typeRestrictions);
ObjectTypeSet getType(const Node &node, const ThrowNode &subnode,
const ObjectTypeSet &typeRestrictions);

Var *getOrCreateVar(std::string_view name);
bool canThrow(const clojure::rt::protobuf::bytecode::Node &node);
Expand Down
9 changes: 5 additions & 4 deletions backend-v2/codegen/ops/IfNode.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "../CodeGen.h"
#include <string>

using namespace std;
using namespace llvm;
Expand Down Expand Up @@ -246,9 +247,9 @@ TypedValue CodeGen::codegen(const Node &node, const IfNode &subnode,
"value that does not match allowed types: ") +
typeRestrictions.toString();
TypedValue msg = dynamicConstructor.createString(errMsg.c_str());
TypedValue rawPtr = valueEncoder.unboxPointer(msg);
memoryManagement.dynamicRetain(msg);
invokeManager.invokeRuntime("throwInternalInconsistencyException_C",
nullptr, {ObjectTypeSet::all()}, {rawPtr});
nullptr, {ObjectTypeSet(stringType)}, {msg});

Builder.CreateUnreachable();

Expand All @@ -271,9 +272,9 @@ TypedValue CodeGen::codegen(const Node &node, const IfNode &subnode,
"value that does not match allowed types: ") +
typeRestrictions.toString();
TypedValue msg = dynamicConstructor.createString(errMsg.c_str());
TypedValue rawPtr = valueEncoder.unboxPointer(msg);
memoryManagement.dynamicRetain(msg);
invokeManager.invokeRuntime("throwInternalInconsistencyException_C",
nullptr, {ObjectTypeSet::all()}, {rawPtr});
nullptr, {ObjectTypeSet(stringType)}, {msg});

Builder.CreateUnreachable();

Expand Down
34 changes: 34 additions & 0 deletions backend-v2/codegen/ops/ThrowNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "../CodeGen.h"
#include "bridge/Exceptions.h"
#include "runtime/ObjectProto.h"

using namespace std;
using namespace llvm;

namespace rt {

TypedValue CodeGen::codegen(const Node &node, const ThrowNode &subnode,
const ObjectTypeSet &typeRestrictions) {
TypedValue ex = codegen(subnode.exception(), ObjectTypeSet::all().boxed());
TypedValue boxedEx = valueEncoder.box(ex);

if (ex.type.isDetermined() && ex.type.determinedType() != exceptionType) {
throwCodeGenerationException(
"class " + ex.type.toString() +
" cannot be cast to class java.lang.Throwable",
node);
}

invokeManager.invokeRuntime("throwException_C", nullptr,
{ObjectTypeSet::all().boxed()}, {boxedEx});

// This point is unreachable because throwException_C is [[noreturn]]
return dynamicConstructor.createNil();
}

ObjectTypeSet CodeGen::getType(const Node &node, const ThrowNode &subnode,
const ObjectTypeSet &typeRestrictions) {
return ObjectTypeSet(nilType);
}

} // namespace rt
7 changes: 7 additions & 0 deletions backend-v2/jit/JITEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,13 @@ void JITEngine::registerRuntimeSymbols() {
runtimeSymbols.insert(absoluteSymbol("JITEngine_slowPath_leave",
(void *)JITEngine_slowPath_leave));

runtimeSymbols.insert(
absoluteSymbol("exceptionToString_C", (void *)exceptionToString_C));
runtimeSymbols.insert(
absoluteSymbol("createException_C", (void *)createException_C));
runtimeSymbols.insert(
absoluteSymbol("deleteException_C", (void *)deleteException_C));

cantFail(jit->getMainJITDylib().define(
absoluteSymbols(std::move(runtimeSymbols))));
}
Expand Down
2 changes: 2 additions & 0 deletions backend-v2/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ set(SOURCES
PersistentArrayMap.c
Var.c
Numbers.c
Exception.c
JITSafety.c)

add_library(runtime STATIC ${SOURCES})
Expand Down Expand Up @@ -142,6 +143,7 @@ set(TEST_MODULES
Var_Race_test
RefcountPerf_test
Numbers_test
Exception_test
)

foreach(TEST_MODULE ${TEST_MODULES})
Expand Down
33 changes: 33 additions & 0 deletions backend-v2/runtime/Exception.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "Exception.h"
#include "Object.h"
#include "RTValue.h"
#include "String.h"
#include <stdio.h>

String *exceptionToString_C(void *exception);
void *createException_C(const char *className, String *message,
RTValue payload);
void deleteException_C(void *exception);

Exception *Exception_createAssertionErrorWithMessage(String *message) {
Exception *self = (Exception *)allocate(sizeof(Exception));
Object_create((Object *)self, exceptionType);
self->bridgedData = createException_C("AssertionError", message, RT_boxNil());
return self;
}

void Exception_destroy(Exception *self) {
deleteException_C(self->bridgedData);
}

uword_t Exception_hash(Exception *self) { return (uword_t)self->bridgedData; }

bool Exception_equals(Exception *self, Exception *other) {
return self->bridgedData == other->bridgedData;
}

String *Exception_toString(Exception *self) {
String *retVal = exceptionToString_C(self->bridgedData);
Ptr_release(self);
return retVal;
}
27 changes: 27 additions & 0 deletions backend-v2/runtime/Exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef RT_EXCEPTION_H
#define RT_EXCEPTION_H

#include "ObjectProto.h"
#include "String.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct Exception {
Object header;
void *bridgedData;
} Exception;

Exception *Exception_createAssertionErrorWithMessage(String *message);

void Exception_destroy(Exception *self);
uword_t Exception_hash(Exception *self);
bool Exception_equals(Exception *self, Exception *other);
String *Exception_toString(Exception *self);

#ifdef __cplusplus
}
#endif

#endif // RT_EXCEPTION_H
6 changes: 4 additions & 2 deletions backend-v2/runtime/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

#ifdef __cplusplus
extern "C" {
#include "runtime/String.h"

#endif

// Base throw function compatible with LanguageException
[[noreturn]] void throwLanguageException_C(const char *name, RTValue message,
RTValue payload);
[[noreturn]] void throwException_C(RTValue exceptionBoxed);

// Standard Clojure-like exceptions
[[noreturn]] void throwArityException_C(int expected, int actual);
Expand All @@ -20,8 +23,7 @@ extern "C" {
[[noreturn]] void throwArithmeticException_C(const char *message);
[[noreturn]] void throwIndexOutOfBoundsException_C(uword_t index,
uword_t count);
[[noreturn]] void
throwInternalInconsistencyException_C(const char *errorMessage);
[[noreturn]] void throwInternalInconsistencyException_C(String *errorMessage);

#ifdef __cplusplus
}
Expand Down
11 changes: 10 additions & 1 deletion backend-v2/runtime/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ inline bool Ptr_isReusable(void* ptr);
#include "BigInteger.h"
#include "Boolean.h"
#include "Class.h"
#include "Exception.h"
#include "ConcurrentHashMap.h"
#include "Double.h"
#include "Function.h"
Expand Down Expand Up @@ -285,6 +286,9 @@ inline void Object_destroy(Object *restrict self, bool deallocateChildren) {
case varType:
Var_destroy((Var *)self);
break;
case exceptionType:
Exception_destroy((Exception *)self);
break;

default:
break;
Expand Down Expand Up @@ -455,6 +459,8 @@ inline uword_t Object_hash(Object *restrict self) {
return PersistentArrayMap_hash((PersistentArrayMap *)self);
case varType:
return Var_hash((Var *)self);
case exceptionType:
return Exception_hash((Exception *)self);
default:
assert(false && "Internal error: hash computation for NaN tagged types "
"should be computed earlier.");
Expand Down Expand Up @@ -534,7 +540,8 @@ inline bool Object_equals(Object *self, Object *other) {
case varType:
return Var_equals((Var *)self, (Var *)other);
break;

case exceptionType:
return Exception_equals((Exception *)self, (Exception *)other);
default:
assert(false && "Internal error: hash computation for NaN tagged types "
"should be computed earlier.");
Expand Down Expand Up @@ -594,6 +601,8 @@ inline String *Object_toString(Object *restrict self) {
return PersistentArrayMap_toString((PersistentArrayMap *)self);
case varType:
return Var_toString((Var *)self);
case exceptionType:
return Exception_toString((Exception *)self);
default:
assert(false && "Internal error: Object_toString got an unsupported type");
}
Expand Down
1 change: 1 addition & 0 deletions backend-v2/runtime/ObjectProto.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum objectType {
persistentArrayMapType, // 16
varType, // 17
objectRootType, // 18
exceptionType, // 19
};

typedef enum objectType objectType;
Expand Down
Loading
Loading