Index: vm/object.cc |
=================================================================== |
--- vm/object.cc (revision 5501) |
+++ vm/object.cc (working copy) |
@@ -79,6 +79,7 @@ |
RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
+RawClass* Object::stackmap_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
RawClass* Object::var_descriptors_class_ = |
reinterpret_cast<RawClass*>(RAW_NULL); |
RawClass* Object::exception_handlers_class_ = |
@@ -137,6 +138,8 @@ |
return kInstructionsClass; |
} else if (raw_class == pc_descriptors_class()) { |
return kPcDescriptorsClass; |
+ } else if (raw_class == stackmap_class()) { |
+ return kStackmapClass; |
} else if (raw_class == var_descriptors_class()) { |
return kLocalVarDescriptorsClass; |
} else if (raw_class == exception_handlers_class()) { |
@@ -184,6 +187,7 @@ |
case kCodeClass: return code_class(); |
case kInstructionsClass: return instructions_class(); |
case kPcDescriptorsClass: return pc_descriptors_class(); |
+ case kStackmapClass: return stackmap_class(); |
case kLocalVarDescriptorsClass: return var_descriptors_class(); |
case kExceptionHandlersClass: return exception_handlers_class(); |
case kContextClass: return context_class(); |
@@ -222,6 +226,7 @@ |
case kCodeClass: return "Code"; |
case kInstructionsClass: return "Instructions"; |
case kPcDescriptorsClass: return "PcDescriptors"; |
+ case kStackmapClass: return "Stackmap"; |
case kLocalVarDescriptorsClass: return "LocalVarDescriptors"; |
case kExceptionHandlersClass: return "ExceptionHandlers"; |
case kContextClass: return "Context"; |
@@ -365,6 +370,9 @@ |
cls = Class::New<PcDescriptors>(); |
pc_descriptors_class_ = cls.raw(); |
+ cls = Class::New<Stackmap>(); |
+ stackmap_class_ = cls.raw(); |
+ |
cls = Class::New<LocalVarDescriptors>(); |
var_descriptors_class_ = cls.raw(); |
@@ -5380,6 +5388,114 @@ |
} |
+// Return the bit offset of the highest bit set. |
+intptr_t Stackmap::Maximum() const { |
+ intptr_t bound = SizeInBits(); |
+ for (intptr_t i = (bound - 1); i >= 0; i--) { |
+ if (IsObject(i)) return i; |
+ } |
+ return kNoMaximum; |
+} |
+ |
+ |
+// Return the bit offset of the lowest bit set. |
+intptr_t Stackmap::Minimum() const { |
+ intptr_t bound = SizeInBits(); |
+ for (intptr_t i = 0; i < bound; i++) { |
+ if (IsObject(i)) return i; |
+ } |
+ return kNoMinimum; |
+} |
+ |
+ |
+bool Stackmap::GetBit(intptr_t bit_offset) const { |
+ ASSERT(InRange(bit_offset)); |
+ int byte_offset = bit_offset >> kBitsPerByteLog2; |
+ int bit_remainder = bit_offset & (kBitsPerByte - 1); |
+ uint8_t byte_mask = 1U << bit_remainder; |
+ uint8_t byte = raw_ptr()->data_[byte_offset]; |
+ return (byte & byte_mask); |
+} |
+ |
+ |
+void Stackmap::SetBit(intptr_t bit_offset, bool value) const { |
+ ASSERT(InRange(bit_offset)); |
+ int byte_offset = bit_offset >> kBitsPerByteLog2; |
+ int bit_remainder = bit_offset & (kBitsPerByte - 1); |
+ uint8_t byte_mask = 1U << bit_remainder; |
+ uint8_t* byte_addr = &(raw_ptr()->data_[byte_offset]); |
+ if (value) { |
+ *byte_addr |= byte_mask; |
+ } else { |
+ *byte_addr &= ~byte_mask; |
+ } |
+} |
+ |
+ |
+RawStackmap* Stackmap::New(uword pc, const Code& code, BitmapBuilder* bmap) { |
+ const Class& cls = Class::Handle(Object::stackmap_class()); |
+ ASSERT(!cls.IsNull()); |
+ ASSERT(bmap != NULL); |
+ Stackmap& result = Stackmap::Handle(); |
+ intptr_t size = bmap->SizeInBytes(); |
+ { |
+ // Stackmap data objects are associated with a code object, allocate them |
+ // in old generation. |
+ RawObject* raw = |
+ Object::Allocate(cls, Stackmap::InstanceSize(size), Heap::kOld); |
+ NoGCScope no_gc; |
+ result ^= raw; |
+ result.set_bitmap_size_in_bytes(size); |
+ } |
+ result.set_pc(pc); |
+ result.set_code(code); |
+ intptr_t bound = bmap->SizeInBits(); |
+ for (intptr_t i = 0; i < bound; i++) { |
+ result.SetBit(i, bmap->Get(i)); |
+ } |
+ return result.raw(); |
+} |
+ |
+ |
+void Stackmap::set_bitmap_size_in_bytes(intptr_t value) const { |
+ // This is only safe because we create a new Smi, which does not cause |
+ // heap allocation. |
+ raw_ptr()->bitmap_size_in_bytes_ = Smi::New(value); |
+} |
+ |
+ |
+void Stackmap::set_pc(uword value) const { |
+ raw_ptr()->pc_ = value; |
+} |
+ |
+ |
+void Stackmap::set_code(const Code& code) const { |
+ StorePointer(&raw_ptr()->code_, code.raw()); |
+} |
+ |
+ |
+const char* Stackmap::ToCString() const { |
+ if (IsNull()) { |
+ return "{null}"; |
+ } else { |
+ intptr_t index = OS::SNPrint(NULL, 0, "0x%lx { ", pc()); |
+ intptr_t alloc_size = index + ((Maximum() + 1) * 2) + 2; // "{ 1 0 .... }". |
+ Isolate* isolate = Isolate::Current(); |
+ char* chars = reinterpret_cast<char*>( |
+ isolate->current_zone()->Allocate(alloc_size)); |
+ index = OS::SNPrint(chars, alloc_size, "0x%lx { ", pc()); |
+ for (intptr_t i = 0; i <= Maximum(); i++) { |
+ index += OS::SNPrint((chars + index), |
+ (alloc_size - index), |
+ "%d ", |
+ IsObject(i) ? 1 : 0); |
+ } |
+ OS::SNPrint((chars + index), (alloc_size - index), "}"); |
+ return chars; |
+ } |
+} |
+ |
+ |
RawString* LocalVarDescriptors::GetName(intptr_t var_index) const { |
ASSERT(var_index < Length()); |
const Array& names = Array::Handle(raw_ptr()->names_); |