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:
cshapiro@google.com 2012-07-13 23:23:45 +00:00
parent f5b544c948
commit e964989681
13 changed files with 120 additions and 54 deletions

View file

@ -148,6 +148,7 @@ void AssemblerBuffer::EmitObject(const Object& object) {
// Since we are going to store the handle as part of the fixup information // Since we are going to store the handle as part of the fixup information
// the handle needs to be a zone handle. // the handle needs to be a zone handle.
ASSERT(object.IsZoneHandle()); ASSERT(object.IsZoneHandle());
ASSERT(object.IsOld());
EmitFixup(new PatchCodeWithHandle(pointer_offsets_, object)); EmitFixup(new PatchCodeWithHandle(pointer_offsets_, object));
cursor_ += kWordSize; // Reserve space for pointer. cursor_ += kWordSize; // Reserve space for pointer.
} }

View file

@ -309,6 +309,7 @@ class LiteralNode : public AstNode {
LiteralNode(intptr_t token_pos, const Instance& literal) LiteralNode(intptr_t token_pos, const Instance& literal)
: AstNode(token_pos), literal_(literal) { : AstNode(token_pos), literal_(literal) {
ASSERT(literal.IsZoneHandle()); ASSERT(literal.IsZoneHandle());
ASSERT(literal.IsSmi() || literal.IsOld());
#if defined(DEBUG) #if defined(DEBUG)
if (literal.IsString()) { if (literal.IsString()) {
ASSERT(String::Cast(literal).IsSymbol()); ASSERT(String::Cast(literal).IsSymbol());

View file

@ -114,7 +114,7 @@ RawBigint* BigintOperations::NewFromCString(const char* str,
ASSERT(IsClamped(result)); ASSERT(IsClamped(result));
return result.raw(); return result.raw();
} else { } else {
return FromDecimalCString(str); return FromDecimalCString(str, space);
} }
} }
@ -169,14 +169,14 @@ RawBigint* BigintOperations::FromDecimalCString(const char* str,
ASSERT(('0' <= c) && (c <= '9')); ASSERT(('0' <= c) && (c <= '9'));
digit = digit * 10 + c - '0'; digit = digit * 10 + c - '0';
} }
Bigint& result = Bigint::Handle(Bigint::Allocate(1, space)); Bigint& result = Bigint::Handle(Bigint::Allocate(1));
result.SetChunkAt(0, digit); result.SetChunkAt(0, digit);
Clamp(result); // Multiplication requires the inputs to be clamped. Clamp(result); // Multiplication requires the inputs to be clamped.
// Read kDigitsPerIteration at a time, and store it in 'increment'. // Read kDigitsPerIteration at a time, and store it in 'increment'.
// Then multiply the temporary result by 10^kDigitsPerIteration and add // Then multiply the temporary result by 10^kDigitsPerIteration and add
// 'increment' to the new result. // '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) { while (str_pos < str_length - 1) {
Chunk digit = 0; Chunk digit = 0;
for (intptr_t i = 0; i < kDigitsPerIteration; i++) { for (intptr_t i = 0; i < kDigitsPerIteration; i++) {
@ -191,6 +191,9 @@ RawBigint* BigintOperations::FromDecimalCString(const char* str,
} }
} }
Clamp(result); Clamp(result);
if ((space == Heap::kOld) && !result.IsOld()) {
result ^= Object::Clone(result, Heap::kOld);
}
return result.raw(); return result.raw();
} }

View file

@ -24,7 +24,7 @@ static const intptr_t kPos = Scanner::kDummyTokenIndex;
// Helper to allocate and return a LocalVariable. // Helper to allocate and return a LocalVariable.
static LocalVariable* NewTestLocalVariable(const char* name) { 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()); const Type& variable_type = Type::ZoneHandle(Type::DynamicType());
return new LocalVariable(kPos, variable_name, variable_type); return new LocalVariable(kPos, variable_name, variable_type);
} }
@ -129,10 +129,12 @@ CODEGEN_TEST_RUN(SmiAddCodegen, Smi::New(5))
CODEGEN_TEST_GENERATE(GenericAddCodegen, test) { CODEGEN_TEST_GENERATE(GenericAddCodegen, test) {
SequenceNode* node_seq = test->node_sequence(); 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))); LiteralNode* b = new LiteralNode(kPos, Smi::ZoneHandle(Smi::New(2)));
BinaryOpNode* add_node_1 = new BinaryOpNode(kPos, Token::kADD, a, b); 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); BinaryOpNode* add_node_2 = new BinaryOpNode(kPos, Token::kADD, add_node_1, c);
node_seq->Add(new ReturnNode(kPos, add_node_2)); node_seq->Add(new ReturnNode(kPos, add_node_2));
} }
@ -179,9 +181,11 @@ CODEGEN_TEST_RUN(BoolAndCodegen, Bool::False())
CODEGEN_TEST_GENERATE(BinaryOpCodegen, test) { CODEGEN_TEST_GENERATE(BinaryOpCodegen, test) {
SequenceNode* node_seq = test->node_sequence(); 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* 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* sub_node = new BinaryOpNode(kPos, Token::kSUB, a, b);
BinaryOpNode* mul_node = new BinaryOpNode(kPos, Token::kMUL, sub_node, c); BinaryOpNode* mul_node = new BinaryOpNode(kPos, Token::kMUL, sub_node, c);
BinaryOpNode* div_node = new BinaryOpNode(kPos, Token::kDIV, mul_node, b); 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) { CODEGEN_TEST_GENERATE(DoubleUnaryOpCodegen, test) {
SequenceNode* node_seq = test->node_sequence(); 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); UnaryOpNode* neg_node = new UnaryOpNode(kPos, Token::kSUB, a);
node_seq->Add(new ReturnNode(kPos, neg_node)); node_seq->Add(new ReturnNode(kPos, neg_node));
} }

View file

@ -742,6 +742,7 @@ void FlowGraphCompiler::CopyParameters() {
__ j(GREATER, &next_parameter, Assembler::kNearJump); __ j(GREATER, &next_parameter, Assembler::kNearJump);
// Check if this named parameter was passed in. // Check if this named parameter was passed in.
__ movl(EAX, Address(EDI, 0)); // Load EAX with the name of the argument. __ 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()); __ CompareObject(EAX, opt_param[i]->name());
__ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump);
// Load EAX with passed-in argument at provided arg_pos, i.e. at // Load EAX with passed-in argument at provided arg_pos, i.e. at

View file

@ -336,6 +336,7 @@ class ConstantVal: public Value {
explicit ConstantVal(const Object& value) explicit ConstantVal(const Object& value)
: value_(value) { : value_(value) {
ASSERT(value.IsZoneHandle()); ASSERT(value.IsZoneHandle());
ASSERT(value.IsSmi() || value.IsOld());
} }
DECLARE_VALUE(Constant) DECLARE_VALUE(Constant)

View file

@ -517,7 +517,7 @@ RawError* Object::Init(Isolate* isolate) {
GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld)); GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
object_store->set_pending_classes(pending_classes); 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); object_store->set_empty_context(context);
// Now that the symbol table is initialized and that the core dictionary as // 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 { RawString* Class::Name() const {
if (raw_ptr()->name_ != String::null()) { if (raw_ptr()->name_ != String::null()) {
return raw_ptr()->name_; return raw_ptr()->name_;
@ -2761,7 +2794,6 @@ RawAbstractType* Type::Canonicalize() const {
index++; index++;
} }
// The type needs to be added to the list. Grow the list if it is full. // 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) { if (index == canonical_types_len) {
const intptr_t kLengthIncrement = 2; // Raw and parameterized. const intptr_t kLengthIncrement = 2; // Raw and parameterized.
const intptr_t new_length = canonical_types.Length() + kLengthIncrement; const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
@ -2772,6 +2804,7 @@ RawAbstractType* Type::Canonicalize() const {
} else { } else {
canonical_types.SetAt(index, *this); canonical_types.SetAt(index, *this);
} }
ASSERT(IsOld());
SetCanonical(); SetCanonical();
return this->raw(); return this->raw();
} }
@ -3414,23 +3447,27 @@ RawAbstractTypeArguments* TypeArguments::Canonicalize() const {
Array& table = Array::Handle(object_store->canonical_type_arguments()); Array& table = Array::Handle(object_store->canonical_type_arguments());
ASSERT(table.Length() > 0); ASSERT(table.Length() > 0);
intptr_t index = 0; intptr_t index = 0;
TypeArguments& other = TypeArguments::Handle(); TypeArguments& result = TypeArguments::Handle();
other ^= table.At(index); result ^= table.At(index);
while (!other.IsNull()) { while (!result.IsNull()) {
if (this->Equals(other)) { if (this->Equals(result)) {
return other.raw(); return result.raw();
} }
other ^= table.At(++index); result ^= table.At(++index);
} }
// Not found. Add 'this' to table. // 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) { if (index == table.Length() - 1) {
table = Array::Grow(table, table.Length() + 4, Heap::kOld); table = Array::Grow(table, table.Length() + 4, Heap::kOld);
object_store->set_canonical_type_arguments(table); object_store->set_canonical_type_arguments(table);
} }
table.SetAt(index, *this); table.SetAt(index, result);
SetCanonical(); result.SetCanonical();
return this->raw(); return result.raw();
} }
@ -4423,6 +4460,7 @@ RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) {
result.set_literal(literal); result.set_literal(literal);
if (kind == Token::kINTEGER) { if (kind == Token::kINTEGER) {
const Integer& value = Integer::Handle(Integer::New(literal, Heap::kOld)); const Integer& value = Integer::Handle(Integer::New(literal, Heap::kOld));
ASSERT(value.IsSmi() || value.IsOld());
result.set_value(value); result.set_value(value);
} else if (kind == Token::kDOUBLE) { } else if (kind == Token::kDOUBLE) {
const Double& value = Double::Handle(Double::NewCanonical(literal)); const Double& value = Double::Handle(Double::NewCanonical(literal));
@ -7548,31 +7586,37 @@ bool Instance::Equals(const Instance& other) const {
RawInstance* Instance::Canonicalize() const { RawInstance* Instance::Canonicalize() const {
ASSERT(!IsNull()); ASSERT(!IsNull());
if (!IsCanonical()) { if (this->IsCanonical()) {
const Class& cls = Class::Handle(this->clazz()); return this->raw();
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();
} }
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();
} }

View file

@ -235,6 +235,8 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
return VMHandles::IsZoneHandle(reinterpret_cast<uword>(this)); 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) { static Object& Handle(Isolate* isolate, RawObject* raw_ptr) {
Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(isolate)); Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(isolate));
obj->SetRaw(raw_ptr); obj->SetRaw(raw_ptr);

View file

@ -32,7 +32,8 @@ void GenerateIncrement(Assembler* assembler) {
// Generate a dart code sequence that embeds a string object in it. // Generate a dart code sequence that embeds a string object in it.
// This is used to test Embedded String objects in the instructions. // This is used to test Embedded String objects in the instructions.
void GenerateEmbedStringInCode(Assembler* assembler, const char* str) { 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); __ LoadObject(EAX, string_object);
__ ret(); __ ret();
} }

View file

@ -32,7 +32,8 @@ void GenerateIncrement(Assembler* assembler) {
// Generate a dart code sequence that embeds a string object in it. // Generate a dart code sequence that embeds a string object in it.
// This is used to test Embedded String objects in the instructions. // This is used to test Embedded String objects in the instructions.
void GenerateEmbedStringInCode(Assembler* assembler, const char* str) { 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); __ LoadObject(RAX, string_object);
__ ret(); __ ret();
} }

View file

@ -106,8 +106,14 @@ static RawTypeArguments* NewTypeArguments(const GrowableObjectArray& objs) {
static ThrowNode* GenerateRethrow(intptr_t token_pos, const Object& obj) { static ThrowNode* GenerateRethrow(intptr_t token_pos, const Object& obj) {
const UnhandledException& excp = UnhandledException::Cast(obj); const UnhandledException& excp = UnhandledException::Cast(obj);
const Instance& exception = Instance::ZoneHandle(excp.exception()); Instance& exception = Instance::ZoneHandle(excp.exception());
const Instance& stack_trace = Instance::ZoneHandle(excp.stacktrace()); 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, return new ThrowNode(token_pos,
new LiteralNode(token_pos, exception), new LiteralNode(token_pos, exception),
new LiteralNode(token_pos, stack_trace)); new LiteralNode(token_pos, stack_trace));
@ -7044,7 +7050,7 @@ RawObject* Parser::EvaluateConstConstructorCall(
GrowableArray<const Object*> arg_values(arguments->length() + 2); GrowableArray<const Object*> arg_values(arguments->length() + 2);
Instance& instance = Instance::Handle(); Instance& instance = Instance::Handle();
if (!constructor.IsFactory()) { if (!constructor.IsFactory()) {
instance = Instance::New(type_class); instance = Instance::New(type_class, Heap::kOld);
if (!type_arguments.IsNull()) { if (!type_arguments.IsNull()) {
if (!type_arguments.IsInstantiated()) { if (!type_arguments.IsInstantiated()) {
ErrorMsg("type must be constant in const constructor"); ErrorMsg("type must be constant in const constructor");

View file

@ -36,7 +36,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler,
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1)); const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2)); const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
const Object& result = Object::ZoneHandle(); 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()); ASSERT(context.isolate() == Isolate::Current());
__ enter(Immediate(0)); __ enter(Immediate(0));
__ LoadObject(CTX, context); __ LoadObject(CTX, context);
@ -119,7 +119,7 @@ static void GenerateCallToCallNativeCFunctionStub(Assembler* assembler,
Dart_NativeFunction native_function = Dart_NativeFunction native_function =
NativeTestEntry_Lookup(native_name, argc); NativeTestEntry_Lookup(native_name, argc);
ASSERT(native_function != NULL); 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()); ASSERT(context.isolate() == Isolate::Current());
__ enter(Immediate(0)); __ enter(Immediate(0));
__ LoadObject(CTX, context); __ LoadObject(CTX, context);

View file

@ -37,7 +37,7 @@ static void GenerateCallToCallRuntimeStub(Assembler* assembler,
const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1)); const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2)); const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
const Object& result = Object::ZoneHandle(); 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()); ASSERT(context.isolate() == Isolate::Current());
__ enter(Immediate(0)); __ enter(Immediate(0));
__ LoadObject(CTX, context); __ LoadObject(CTX, context);
@ -118,7 +118,7 @@ static void GenerateCallToCallNativeCFunctionStub(Assembler* assembler,
Dart_NativeFunction native_function = Dart_NativeFunction native_function =
NativeTestEntry_Lookup(native_name, argc); NativeTestEntry_Lookup(native_name, argc);
ASSERT(native_function != NULL); 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()); ASSERT(context.isolate() == Isolate::Current());
__ enter(Immediate(0)); __ enter(Immediate(0));
__ LoadObject(CTX, context); __ LoadObject(CTX, context);