mirror of
https://github.com/corda/corda.git
synced 2025-01-09 14:33:30 +00:00
453ceb42ab
Unlike the interpreter, the JIT compiler tries to resolve all the symbols referenced by a method when compiling that method. However, this can backfire if a symbol cannot be resolved: we end up throwing an e.g. NoClassDefFoundError for code which may never be executed. This is particularly troublesome for code which supports multiple APIs, choosing one at runtime. The solution is to defer to stub code for symbols which can't be resolved at JIT compile time. Such a stub will try again at runtime to resolve the needed symbol and throw an appropriate error if it still can't be found.
111 lines
2.3 KiB
C++
111 lines
2.3 KiB
C++
/* Copyright (c) 2008, Avian Contributors
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
for any purpose with or without fee is hereby granted, provided
|
|
that the above copyright notice and this permission notice appear
|
|
in all copies.
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
details. */
|
|
|
|
#ifndef ZONE_H
|
|
#define ZONE_H
|
|
|
|
#include "system.h"
|
|
#include "allocator.h"
|
|
|
|
namespace vm {
|
|
|
|
class Zone: public Allocator {
|
|
public:
|
|
class Segment {
|
|
public:
|
|
Segment(Segment* next, unsigned size): next(next), size(size) { }
|
|
|
|
Segment* next;
|
|
uintptr_t size;
|
|
uint8_t data[0];
|
|
};
|
|
|
|
Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
|
|
s(s),
|
|
allocator(allocator),
|
|
segment(0),
|
|
position(0),
|
|
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
|
|
minimumFootprint - sizeof(Segment))
|
|
{ }
|
|
|
|
~Zone() {
|
|
dispose();
|
|
}
|
|
|
|
void dispose() {
|
|
for (Segment* seg = segment, *next; seg; seg = next) {
|
|
next = seg->next;
|
|
allocator->free(seg, sizeof(Segment) + seg->size);
|
|
}
|
|
|
|
segment = 0;
|
|
}
|
|
|
|
bool ensure(unsigned space) {
|
|
if (segment == 0 or position + space > segment->size) {
|
|
unsigned size = max
|
|
(space, max
|
|
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
|
|
+ sizeof(Segment);
|
|
|
|
// pad to page size
|
|
size = (size + (LikelyPageSizeInBytes - 1))
|
|
& ~(LikelyPageSizeInBytes - 1);
|
|
|
|
void* p = allocator->tryAllocate(size);
|
|
if (p == 0) {
|
|
size = space + sizeof(Segment);
|
|
void* p = allocator->tryAllocate(size);
|
|
if (p == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
segment = new (p) Segment(segment, size - sizeof(Segment));
|
|
position = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual void* tryAllocate(unsigned size) {
|
|
size = pad(size);
|
|
if (ensure(size)) {
|
|
void* r = segment->data + position;
|
|
position += size;
|
|
return r;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
virtual void* allocate(unsigned size) {
|
|
void* p = tryAllocate(size);
|
|
expect(s, p);
|
|
return p;
|
|
}
|
|
|
|
virtual void free(const void*, unsigned) {
|
|
// not supported
|
|
abort(s);
|
|
}
|
|
|
|
System* s;
|
|
Allocator* allocator;
|
|
void* context;
|
|
Segment* segment;
|
|
unsigned position;
|
|
unsigned minimumFootprint;
|
|
};
|
|
|
|
} // namespace vm
|
|
|
|
#endif//ZONE_H
|