diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc index 446c78a630f..794f937783c 100644 --- a/runtime/vm/assembler.cc +++ b/runtime/vm/assembler.cc @@ -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. } diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h index b02a10d9c5b..ce4e064d638 100644 --- a/runtime/vm/ast.h +++ b/runtime/vm/ast.h @@ -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()); diff --git a/runtime/vm/bigint_operations.cc b/runtime/vm/bigint_operations.cc index d453a2a4d68..d4c77437345 100644 --- a/runtime/vm/bigint_operations.cc +++ b/runtime/vm/bigint_operations.cc @@ -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(); } diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc index 7c080cf150c..61bc5c0799d 100644 --- a/runtime/vm/code_generator_test.cc +++ b/runtime/vm/code_generator_test.cc @@ -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)); } diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc index 532725591b6..1e67f813bf2 100644 --- a/runtime/vm/flow_graph_compiler_ia32.cc +++ b/runtime/vm/flow_graph_compiler_ia32.cc @@ -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 diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h index 00dcde25d54..8df33ee0dc6 100644 --- a/runtime/vm/intermediate_language.h +++ b/runtime/vm/intermediate_language.h @@ -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) diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 1d0e862e03e..ae14d233274 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -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(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(); } diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 676b724c3da..5d6988c46a0 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -235,6 +235,8 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER); return VMHandles::IsZoneHandle(reinterpret_cast(this)); } + static RawObject* Clone(const Object& src, Heap::Space space = Heap::kNew); + static Object& Handle(Isolate* isolate, RawObject* raw_ptr) { Object* obj = reinterpret_cast(VMHandles::AllocateHandle(isolate)); obj->SetRaw(raw_ptr); diff --git a/runtime/vm/object_ia32_test.cc b/runtime/vm/object_ia32_test.cc index 2c9785087d8..2c28cc1b57a 100644 --- a/runtime/vm/object_ia32_test.cc +++ b/runtime/vm/object_ia32_test.cc @@ -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(); } diff --git a/runtime/vm/object_x64_test.cc b/runtime/vm/object_x64_test.cc index e1e64d203e8..74c0e5cd529 100644 --- a/runtime/vm/object_x64_test.cc +++ b/runtime/vm/object_x64_test.cc @@ -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(); } diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc index 8f9301e8067..fa4ef4d941a 100644 --- a/runtime/vm/parser.cc +++ b/runtime/vm/parser.cc @@ -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 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"); diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc index e494e97b6cb..b1591d270cd 100644 --- a/runtime/vm/stub_code_ia32_test.cc +++ b/runtime/vm/stub_code_ia32_test.cc @@ -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); diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc index 2fc99bd2edb..95fc3a56478 100644 --- a/runtime/vm/stub_code_x64_test.cc +++ b/runtime/vm/stub_code_x64_test.cc @@ -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);