mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Ensure objects emitted in code are allocated in old space.
BUG=3866 Review URL: https://chromiumcodereview.appspot.com//10786003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@9649 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
f5b544c948
commit
e964989681
13 changed files with 120 additions and 54 deletions
|
@ -148,6 +148,7 @@ void AssemblerBuffer::EmitObject(const Object& object) {
|
|||
// Since we are going to store the handle as part of the fixup information
|
||||
// the handle needs to be a zone handle.
|
||||
ASSERT(object.IsZoneHandle());
|
||||
ASSERT(object.IsOld());
|
||||
EmitFixup(new PatchCodeWithHandle(pointer_offsets_, object));
|
||||
cursor_ += kWordSize; // Reserve space for pointer.
|
||||
}
|
||||
|
|
|
@ -309,6 +309,7 @@ class LiteralNode : public AstNode {
|
|||
LiteralNode(intptr_t token_pos, const Instance& literal)
|
||||
: AstNode(token_pos), literal_(literal) {
|
||||
ASSERT(literal.IsZoneHandle());
|
||||
ASSERT(literal.IsSmi() || literal.IsOld());
|
||||
#if defined(DEBUG)
|
||||
if (literal.IsString()) {
|
||||
ASSERT(String::Cast(literal).IsSymbol());
|
||||
|
|
|
@ -114,7 +114,7 @@ RawBigint* BigintOperations::NewFromCString(const char* str,
|
|||
ASSERT(IsClamped(result));
|
||||
return result.raw();
|
||||
} else {
|
||||
return FromDecimalCString(str);
|
||||
return FromDecimalCString(str, space);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,14 +169,14 @@ RawBigint* BigintOperations::FromDecimalCString(const char* str,
|
|||
ASSERT(('0' <= c) && (c <= '9'));
|
||||
digit = digit * 10 + c - '0';
|
||||
}
|
||||
Bigint& result = Bigint::Handle(Bigint::Allocate(1, space));
|
||||
Bigint& result = Bigint::Handle(Bigint::Allocate(1));
|
||||
result.SetChunkAt(0, digit);
|
||||
Clamp(result); // Multiplication requires the inputs to be clamped.
|
||||
|
||||
// Read kDigitsPerIteration at a time, and store it in 'increment'.
|
||||
// Then multiply the temporary result by 10^kDigitsPerIteration and add
|
||||
// 'increment' to the new result.
|
||||
const Bigint& increment = Bigint::Handle(Bigint::Allocate(1, space));
|
||||
const Bigint& increment = Bigint::Handle(Bigint::Allocate(1));
|
||||
while (str_pos < str_length - 1) {
|
||||
Chunk digit = 0;
|
||||
for (intptr_t i = 0; i < kDigitsPerIteration; i++) {
|
||||
|
@ -191,6 +191,9 @@ RawBigint* BigintOperations::FromDecimalCString(const char* str,
|
|||
}
|
||||
}
|
||||
Clamp(result);
|
||||
if ((space == Heap::kOld) && !result.IsOld()) {
|
||||
result ^= Object::Clone(result, Heap::kOld);
|
||||
}
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ static const intptr_t kPos = Scanner::kDummyTokenIndex;
|
|||
|
||||
// Helper to allocate and return a LocalVariable.
|
||||
static LocalVariable* NewTestLocalVariable(const char* name) {
|
||||
const String& variable_name = String::ZoneHandle(String::New(name));
|
||||
const String& variable_name = String::ZoneHandle(String::NewSymbol(name));
|
||||
const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
|
||||
return new LocalVariable(kPos, variable_name, variable_type);
|
||||
}
|
||||
|
@ -129,10 +129,12 @@ CODEGEN_TEST_RUN(SmiAddCodegen, Smi::New(5))
|
|||
|
||||
CODEGEN_TEST_GENERATE(GenericAddCodegen, test) {
|
||||
SequenceNode* node_seq = test->node_sequence();
|
||||
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.2)));
|
||||
LiteralNode* a =
|
||||
new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.2, Heap::kOld)));
|
||||
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
||||
BinaryOpNode* add_node_1 = new BinaryOpNode(kPos, Token::kADD, a, b);
|
||||
LiteralNode* c = new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.8)));
|
||||
LiteralNode* c =
|
||||
new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.8, Heap::kOld)));
|
||||
BinaryOpNode* add_node_2 = new BinaryOpNode(kPos, Token::kADD, add_node_1, c);
|
||||
node_seq->Add(new ReturnNode(kPos, add_node_2));
|
||||
}
|
||||
|
@ -179,9 +181,11 @@ CODEGEN_TEST_RUN(BoolAndCodegen, Bool::False())
|
|||
|
||||
CODEGEN_TEST_GENERATE(BinaryOpCodegen, test) {
|
||||
SequenceNode* node_seq = test->node_sequence();
|
||||
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12)));
|
||||
LiteralNode* a =
|
||||
new LiteralNode(kPos, Double::ZoneHandle(Double::New(12, Heap::kOld)));
|
||||
LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
|
||||
LiteralNode* c = new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.5)));
|
||||
LiteralNode* c =
|
||||
new LiteralNode(kPos, Double::ZoneHandle(Double::New(0.5, Heap::kOld)));
|
||||
BinaryOpNode* sub_node = new BinaryOpNode(kPos, Token::kSUB, a, b);
|
||||
BinaryOpNode* mul_node = new BinaryOpNode(kPos, Token::kMUL, sub_node, c);
|
||||
BinaryOpNode* div_node = new BinaryOpNode(kPos, Token::kDIV, mul_node, b);
|
||||
|
@ -251,7 +255,8 @@ CODEGEN_TEST_RUN(SmiUnaryOpCodegen, Smi::New(-12))
|
|||
|
||||
CODEGEN_TEST_GENERATE(DoubleUnaryOpCodegen, test) {
|
||||
SequenceNode* node_seq = test->node_sequence();
|
||||
LiteralNode* a = new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.0)));
|
||||
LiteralNode* a =
|
||||
new LiteralNode(kPos, Double::ZoneHandle(Double::New(12.0, Heap::kOld)));
|
||||
UnaryOpNode* neg_node = new UnaryOpNode(kPos, Token::kSUB, a);
|
||||
node_seq->Add(new ReturnNode(kPos, neg_node));
|
||||
}
|
||||
|
|
|
@ -742,6 +742,7 @@ void FlowGraphCompiler::CopyParameters() {
|
|||
__ j(GREATER, &next_parameter, Assembler::kNearJump);
|
||||
// Check if this named parameter was passed in.
|
||||
__ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument.
|
||||
ASSERT(opt_param[i]->name().IsSymbol());
|
||||
__ CompareObject(EAX, opt_param[i]->name());
|
||||
__ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
|
||||
// Load EAX with passed-in argument at provided arg_pos, i.e. at
|
||||
|
|
|
@ -336,6 +336,7 @@ class ConstantVal: public Value {
|
|||
explicit ConstantVal(const Object& value)
|
||||
: value_(value) {
|
||||
ASSERT(value.IsZoneHandle());
|
||||
ASSERT(value.IsSmi() || value.IsOld());
|
||||
}
|
||||
|
||||
DECLARE_VALUE(Constant)
|
||||
|
|
|
@ -517,7 +517,7 @@ RawError* Object::Init(Isolate* isolate) {
|
|||
GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
|
||||
object_store->set_pending_classes(pending_classes);
|
||||
|
||||
Context& context = Context::Handle(Context::New(0));
|
||||
Context& context = Context::Handle(Context::New(0, Heap::kOld));
|
||||
object_store->set_empty_context(context);
|
||||
|
||||
// Now that the symbol table is initialized and that the core dictionary as
|
||||
|
@ -1003,6 +1003,39 @@ RawObject* Object::Allocate(const Class& cls,
|
|||
}
|
||||
|
||||
|
||||
class StoreBufferObjectPointerVisitor : public ObjectPointerVisitor {
|
||||
public:
|
||||
explicit StoreBufferObjectPointerVisitor(Isolate* isolate) :
|
||||
ObjectPointerVisitor(isolate) {
|
||||
}
|
||||
void VisitPointers(RawObject** first, RawObject** last) {
|
||||
for (RawObject** curr = first; curr <= last; ++curr) {
|
||||
if ((*curr)->IsNewObject()) {
|
||||
uword ptr = reinterpret_cast<uword>(curr);
|
||||
isolate()->store_buffer()->AddPointer(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreBufferObjectPointerVisitor);
|
||||
};
|
||||
|
||||
|
||||
RawObject* Object::Clone(const Object& src, Heap::Space space) {
|
||||
const Class& cls = Class::Handle(src.clazz());
|
||||
intptr_t size = src.raw()->Size();
|
||||
RawObject* raw_obj = Object::Allocate(cls, size, space);
|
||||
NoGCScope no_gc;
|
||||
memmove(raw_obj->ptr(), src.raw()->ptr(), size);
|
||||
if (space == Heap::kOld) {
|
||||
StoreBufferObjectPointerVisitor visitor(Isolate::Current());
|
||||
raw_obj->VisitPointers(&visitor);
|
||||
}
|
||||
return raw_obj;
|
||||
}
|
||||
|
||||
|
||||
RawString* Class::Name() const {
|
||||
if (raw_ptr()->name_ != String::null()) {
|
||||
return raw_ptr()->name_;
|
||||
|
@ -2761,7 +2794,6 @@ RawAbstractType* Type::Canonicalize() const {
|
|||
index++;
|
||||
}
|
||||
// The type needs to be added to the list. Grow the list if it is full.
|
||||
// TODO(srdjan): Copy type into old space if canonicalized?
|
||||
if (index == canonical_types_len) {
|
||||
const intptr_t kLengthIncrement = 2; // Raw and parameterized.
|
||||
const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
|
||||
|
@ -2772,6 +2804,7 @@ RawAbstractType* Type::Canonicalize() const {
|
|||
} else {
|
||||
canonical_types.SetAt(index, *this);
|
||||
}
|
||||
ASSERT(IsOld());
|
||||
SetCanonical();
|
||||
return this->raw();
|
||||
}
|
||||
|
@ -3414,23 +3447,27 @@ RawAbstractTypeArguments* TypeArguments::Canonicalize() const {
|
|||
Array& table = Array::Handle(object_store->canonical_type_arguments());
|
||||
ASSERT(table.Length() > 0);
|
||||
intptr_t index = 0;
|
||||
TypeArguments& other = TypeArguments::Handle();
|
||||
other ^= table.At(index);
|
||||
while (!other.IsNull()) {
|
||||
if (this->Equals(other)) {
|
||||
return other.raw();
|
||||
TypeArguments& result = TypeArguments::Handle();
|
||||
result ^= table.At(index);
|
||||
while (!result.IsNull()) {
|
||||
if (this->Equals(result)) {
|
||||
return result.raw();
|
||||
}
|
||||
other ^= table.At(++index);
|
||||
result ^= table.At(++index);
|
||||
}
|
||||
// Not found. Add 'this' to table.
|
||||
// TODO(srdjan): Copy 'this' into old space if canonicalized?
|
||||
result ^= this->raw();
|
||||
if (result.IsNew()) {
|
||||
result ^= Object::Clone(result, Heap::kOld);
|
||||
}
|
||||
ASSERT(result.IsOld());
|
||||
if (index == table.Length() - 1) {
|
||||
table = Array::Grow(table, table.Length() + 4, Heap::kOld);
|
||||
object_store->set_canonical_type_arguments(table);
|
||||
}
|
||||
table.SetAt(index, *this);
|
||||
SetCanonical();
|
||||
return this->raw();
|
||||
table.SetAt(index, result);
|
||||
result.SetCanonical();
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
||||
|
@ -4423,6 +4460,7 @@ RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) {
|
|||
result.set_literal(literal);
|
||||
if (kind == Token::kINTEGER) {
|
||||
const Integer& value = Integer::Handle(Integer::New(literal, Heap::kOld));
|
||||
ASSERT(value.IsSmi() || value.IsOld());
|
||||
result.set_value(value);
|
||||
} else if (kind == Token::kDOUBLE) {
|
||||
const Double& value = Double::Handle(Double::NewCanonical(literal));
|
||||
|
@ -7548,31 +7586,37 @@ bool Instance::Equals(const Instance& other) const {
|
|||
|
||||
RawInstance* Instance::Canonicalize() const {
|
||||
ASSERT(!IsNull());
|
||||
if (!IsCanonical()) {
|
||||
const Class& cls = Class::Handle(this->clazz());
|
||||
Array& constants = Array::Handle(cls.constants());
|
||||
const intptr_t constants_len = constants.Length();
|
||||
// Linear search to see whether this value is already present in the
|
||||
// list of canonicalized constants.
|
||||
Instance& norm_value = Instance::Handle();
|
||||
intptr_t index = 0;
|
||||
while (index < constants_len) {
|
||||
norm_value ^= constants.At(index);
|
||||
if (norm_value.IsNull()) {
|
||||
break;
|
||||
}
|
||||
if (this->Equals(norm_value)) {
|
||||
return norm_value.raw();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// The value needs to be added to the list. Grow the list if
|
||||
// it is full.
|
||||
// TODO(srdjan): Copy instance into old space if canonicalized?
|
||||
cls.InsertCanonicalConstant(index, *this);
|
||||
SetCanonical();
|
||||
if (this->IsCanonical()) {
|
||||
return this->raw();
|
||||
}
|
||||
return this->raw();
|
||||
Instance& result = Instance::Handle();
|
||||
const Class& cls = Class::Handle(this->clazz());
|
||||
Array& constants = Array::Handle(cls.constants());
|
||||
const intptr_t constants_len = constants.Length();
|
||||
// Linear search to see whether this value is already present in the
|
||||
// list of canonicalized constants.
|
||||
intptr_t index = 0;
|
||||
while (index < constants_len) {
|
||||
result ^= constants.At(index);
|
||||
if (result.IsNull()) {
|
||||
break;
|
||||
}
|
||||
if (this->Equals(result)) {
|
||||
return result.raw();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// The value needs to be added to the list. Grow the list if
|
||||
// it is full.
|
||||
result ^= this->raw();
|
||||
if (result.IsNew()) {
|
||||
// Create a canonical object in old space.
|
||||
result ^= Object::Clone(result, Heap::kOld);
|
||||
}
|
||||
ASSERT(result.IsOld());
|
||||
cls.InsertCanonicalConstant(index, result);
|
||||
result.SetCanonical();
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -235,6 +235,8 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
|||
return VMHandles::IsZoneHandle(reinterpret_cast<uword>(this));
|
||||
}
|
||||
|
||||
static RawObject* Clone(const Object& src, Heap::Space space = Heap::kNew);
|
||||
|
||||
static Object& Handle(Isolate* isolate, RawObject* raw_ptr) {
|
||||
Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(isolate));
|
||||
obj->SetRaw(raw_ptr);
|
||||
|
|
|
@ -32,7 +32,8 @@ void GenerateIncrement(Assembler* assembler) {
|
|||
// Generate a dart code sequence that embeds a string object in it.
|
||||
// This is used to test Embedded String objects in the instructions.
|
||||
void GenerateEmbedStringInCode(Assembler* assembler, const char* str) {
|
||||
const String& string_object = String::ZoneHandle(String::New(str));
|
||||
const String& string_object =
|
||||
String::ZoneHandle(String::New(str, Heap::kOld));
|
||||
__ LoadObject(EAX, string_object);
|
||||
__ ret();
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ void GenerateIncrement(Assembler* assembler) {
|
|||
// Generate a dart code sequence that embeds a string object in it.
|
||||
// This is used to test Embedded String objects in the instructions.
|
||||
void GenerateEmbedStringInCode(Assembler* assembler, const char* str) {
|
||||
const String& string_object = String::ZoneHandle(String::New(str));
|
||||
const String& string_object =
|
||||
String::ZoneHandle(String::New(str, Heap::kOld));
|
||||
__ LoadObject(RAX, string_object);
|
||||
__ ret();
|
||||
}
|
||||
|
|
|
@ -106,8 +106,14 @@ static RawTypeArguments* NewTypeArguments(const GrowableObjectArray& objs) {
|
|||
|
||||
static ThrowNode* GenerateRethrow(intptr_t token_pos, const Object& obj) {
|
||||
const UnhandledException& excp = UnhandledException::Cast(obj);
|
||||
const Instance& exception = Instance::ZoneHandle(excp.exception());
|
||||
const Instance& stack_trace = Instance::ZoneHandle(excp.stacktrace());
|
||||
Instance& exception = Instance::ZoneHandle(excp.exception());
|
||||
if (exception.IsNew()) {
|
||||
exception ^= Object::Clone(exception, Heap::kOld);
|
||||
}
|
||||
Instance& stack_trace = Instance::ZoneHandle(excp.stacktrace());
|
||||
if (stack_trace.IsNew()) {
|
||||
stack_trace ^= Object::Clone(stack_trace, Heap::kOld);
|
||||
}
|
||||
return new ThrowNode(token_pos,
|
||||
new LiteralNode(token_pos, exception),
|
||||
new LiteralNode(token_pos, stack_trace));
|
||||
|
@ -7044,7 +7050,7 @@ RawObject* Parser::EvaluateConstConstructorCall(
|
|||
GrowableArray<const Object*> arg_values(arguments->length() + 2);
|
||||
Instance& instance = Instance::Handle();
|
||||
if (!constructor.IsFactory()) {
|
||||
instance = Instance::New(type_class);
|
||||
instance = Instance::New(type_class, Heap::kOld);
|
||||
if (!type_arguments.IsNull()) {
|
||||
if (!type_arguments.IsInstantiated()) {
|
||||
ErrorMsg("type must be constant in const constructor");
|
||||
|
|
|
@ -36,7 +36,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler,
|
|||
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
|
||||
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
|
||||
const Object& result = Object::ZoneHandle();
|
||||
const Context& context = Context::ZoneHandle(Context::New(0));
|
||||
const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld));
|
||||
ASSERT(context.isolate() == Isolate::Current());
|
||||
__ enter(Immediate(0));
|
||||
__ LoadObject(CTX, context);
|
||||
|
@ -119,7 +119,7 @@ static void GenerateCallToCallNativeCFunctionStub(Assembler* assembler,
|
|||
Dart_NativeFunction native_function =
|
||||
NativeTestEntry_Lookup(native_name, argc);
|
||||
ASSERT(native_function != NULL);
|
||||
const Context& context = Context::ZoneHandle(Context::New(0));
|
||||
const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld));
|
||||
ASSERT(context.isolate() == Isolate::Current());
|
||||
__ enter(Immediate(0));
|
||||
__ LoadObject(CTX, context);
|
||||
|
|
|
@ -37,7 +37,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler,
|
|||
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
|
||||
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
|
||||
const Object& result = Object::ZoneHandle();
|
||||
const Context& context = Context::ZoneHandle(Context::New(0));
|
||||
const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld));
|
||||
ASSERT(context.isolate() == Isolate::Current());
|
||||
__ enter(Immediate(0));
|
||||
__ LoadObject(CTX, context);
|
||||
|
@ -118,7 +118,7 @@ static void GenerateCallToCallNativeCFunctionStub(Assembler* assembler,
|
|||
Dart_NativeFunction native_function =
|
||||
NativeTestEntry_Lookup(native_name, argc);
|
||||
ASSERT(native_function != NULL);
|
||||
const Context& context = Context::ZoneHandle(Context::New(0));
|
||||
const Context& context = Context::ZoneHandle(Context::New(0, Heap::kOld));
|
||||
ASSERT(context.isolate() == Isolate::Current());
|
||||
__ enter(Immediate(0));
|
||||
__ LoadObject(CTX, context);
|
||||
|
|
Loading…
Reference in a new issue