Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Unified Diff: dart/runtime/vm/object.cc

Issue 119673004: Version 1.1.0-dev.5.2 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart/runtime/vm/object.h ('k') | dart/runtime/vm/object_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/runtime/vm/object.cc
===================================================================
--- dart/runtime/vm/object.cc (revision 31530)
+++ dart/runtime/vm/object.cc (working copy)
@@ -1808,6 +1808,128 @@
}
+intptr_t Class::FindFunctionIndex(const Function& needle) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsFinalized(isolate) != Error::null()) {
+ return -1;
+ }
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= functions();
+ ASSERT(!funcs.IsNull());
+ Function& function = reused_handles.FunctionHandle();
+ const intptr_t len = funcs.Length();
+ for (intptr_t i = 0; i < len; i++) {
+ function ^= funcs.At(i);
+ if (function.raw() == needle.raw()) {
+ return i;
+ }
+ }
+ // No function found.
+ return -1;
+}
+
+
+RawFunction* Class::FunctionFromIndex(intptr_t idx) const {
+ const Array& funcs = Array::Handle(functions());
+ if ((idx < 0) || (idx >= funcs.Length())) {
+ return Function::null();
+ }
+ Function& func = Function::Handle();
+ func ^= funcs.At(idx);
+ ASSERT(!func.IsNull());
+ return func.raw();
+}
+
+
+RawFunction* Class::ImplicitClosureFunctionFromIndex(intptr_t idx) const {
+ const Array& funcs = Array::Handle(functions());
+ if ((idx < 0) || (idx >= funcs.Length())) {
+ return Function::null();
+ }
+ Function& func = Function::Handle();
+ func ^= funcs.At(idx);
+ ASSERT(!func.IsNull());
+ if (!func.HasImplicitClosureFunction()) {
+ return Function::null();
+ }
+ const Function& closure_func =
+ Function::Handle(func.ImplicitClosureFunction());
+ ASSERT(!closure_func.IsNull());
+ return closure_func.raw();
+}
+
+
+intptr_t Class::FindImplicitClosureFunctionIndex(const Function& needle) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsFinalized(isolate) != Error::null()) {
+ return -1;
+ }
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= functions();
+ ASSERT(!funcs.IsNull());
+ Function& function = reused_handles.FunctionHandle();
+ Function& implicit_closure = Function::Handle();
+ const intptr_t len = funcs.Length();
+ for (intptr_t i = 0; i < len; i++) {
+ function ^= funcs.At(i);
+ implicit_closure ^= function.implicit_closure_function();
+ if (implicit_closure.IsNull()) {
+ // Skip non-implicit closure functions.
+ continue;
+ }
+ if (needle.raw() == implicit_closure.raw()) {
+ return i;
+ }
+ }
+ // No function found.
+ return -1;
+}
+
+
+
+intptr_t Class::FindInvocationDispatcherFunctionIndex(
+ const Function& needle) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsFinalized(isolate) != Error::null()) {
+ return -1;
+ }
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= invocation_dispatcher_cache();
+ ASSERT(!funcs.IsNull());
+ Object& object = reused_handles.ObjectHandle();
+ const intptr_t len = funcs.Length();
+ for (intptr_t i = 0; i < len; i++) {
+ object = funcs.At(i);
+ // The invocation_dispatcher_cache is a table with some entries that
+ // are functions.
+ if (object.IsFunction()) {
+ if (Function::Cast(object).raw() == needle.raw()) {
+ return i;
+ }
+ }
+ }
+ // No function found.
+ return -1;
+}
+
+
+
+RawFunction* Class::InvocationDispatcherFunctionFromIndex(intptr_t idx) const {
+ ReusableHandleScope reused_handles(Isolate::Current());
+ Array& dispatcher_cache = reused_handles.ArrayHandle();
+ dispatcher_cache ^= invocation_dispatcher_cache();
+ Object& object = reused_handles.ObjectHandle();
+ object = dispatcher_cache.At(idx);
+ if (!object.IsFunction()) {
+ return Function::null();
+ }
+ return Function::Cast(object).raw();
+}
+
+
void Class::AddClosureFunction(const Function& function) const {
GrowableObjectArray& closures =
GrowableObjectArray::Handle(raw_ptr()->closure_functions_);
@@ -1848,7 +1970,40 @@
return closure.raw();
}
+intptr_t Class::FindClosureIndex(const Function& needle) const {
+ if (closures() == GrowableObjectArray::null()) {
+ return -1;
+ }
+ Isolate* isolate = Isolate::Current();
+ ReusableHandleScope reused_handles(isolate);
+ const GrowableObjectArray& closures_array =
+ GrowableObjectArray::Handle(isolate, closures());
+ Function& closure = reused_handles.FunctionHandle();
+ intptr_t num_closures = closures_array.Length();
+ for (intptr_t i = 0; i < num_closures; i++) {
+ closure ^= closures_array.At(i);
+ ASSERT(!closure.IsNull());
+ if (closure.raw() == needle.raw()) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+RawFunction* Class::ClosureFunctionFromIndex(intptr_t idx) const {
+ const GrowableObjectArray& closures_array =
+ GrowableObjectArray::Handle(closures());
+ if ((idx < 0) || (idx >= closures_array.Length())) {
+ return Function::null();
+ }
+ Function& func = Function::Handle();
+ func ^= closures_array.At(idx);
+ ASSERT(!func.IsNull());
+ return func.raw();
+}
+
+
void Class::set_signature_function(const Function& value) const {
ASSERT(value.IsClosureFunction() || value.IsSignatureFunction());
StorePointer(&raw_ptr()->signature_function_, value.raw());
@@ -1985,6 +2140,7 @@
break;
}
sup_type = cls.super_type();
+ ClassFinalizer::ResolveType(cls, sup_type);
cls = sup_type.type_class();
} while (true);
set_num_type_arguments(num_type_args);
@@ -2399,6 +2555,44 @@
}
+intptr_t Class::FindFieldIndex(const Field& needle) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsFinalized(isolate) != Error::null()) {
+ return -1;
+ }
+ ReusableHandleScope reused_handles(isolate);
+ Array& fields_array = reused_handles.ArrayHandle();
+ fields_array ^= fields();
+ ASSERT(!fields_array.IsNull());
+ Field& field = reused_handles.FieldHandle();
+ String& field_name = reused_handles.StringHandle();
+ String& needle_name = String::Handle(isolate);
+ needle_name ^= needle.name();
+ const intptr_t len = fields_array.Length();
+ for (intptr_t i = 0; i < len; i++) {
+ field ^= fields_array.At(i);
+ field_name ^= field.name();
+ if (field_name.Equals(needle_name)) {
+ return i;
+ }
+ }
+ // No field found.
+ return -1;
+}
+
+
+RawField* Class::FieldFromIndex(intptr_t idx) const {
+ const Array& flds = Array::Handle(fields());
+ if ((idx < 0) || (idx >= flds.Length())) {
+ return Field::null();
+ }
+ Field& field = Field::Handle();
+ field ^= flds.At(idx);
+ ASSERT(!field.IsNull());
+ return field.raw();
+}
+
+
template <class FakeInstance>
RawClass* Class::New(intptr_t index) {
ASSERT(Object::class_class() != Class::null());
@@ -3248,7 +3442,7 @@
const char* user_visible_class_name =
String::Handle(UserVisibleName()).ToCString();
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id());
+ jsobj.AddPropertyF("id", "classes/%" Pd "", id());
jsobj.AddProperty("name", internal_class_name);
jsobj.AddProperty("user_name", user_visible_class_name);
if (!ref) {
@@ -4011,6 +4205,19 @@
}
+RawAbstractTypeArguments* InstantiatedTypeArguments::Canonicalize() const {
+ const intptr_t num_types = Length();
+ const TypeArguments& type_args = TypeArguments::Handle(
+ TypeArguments::New(num_types, Heap::kOld));
+ AbstractType& type = AbstractType::Handle();
+ for (intptr_t i = 0; i < num_types; i++) {
+ type = TypeAt(i);
+ type_args.SetTypeAt(i, type);
+ }
+ return type_args.Canonicalize();
+}
+
+
void InstantiatedTypeArguments::set_uninstantiated_type_arguments(
const AbstractTypeArguments& value) const {
StorePointer(&raw_ptr()->uninstantiated_type_arguments_, value.raw());
@@ -4360,6 +4567,54 @@
}
+const char* Function::KindToCString(RawFunction::Kind kind) {
+ switch (kind) {
+ case RawFunction::kRegularFunction:
+ return "kRegularFunction";
+ break;
+ case RawFunction::kClosureFunction:
+ return "kClosureFunction";
+ break;
+ case RawFunction::kSignatureFunction:
+ return "kSignatureFunction";
+ break;
+ case RawFunction::kGetterFunction:
+ return "kGetterFunction";
+ break;
+ case RawFunction::kSetterFunction:
+ return "kSetterFunction";
+ break;
+ case RawFunction::kConstructor:
+ return "kConstructor";
+ break;
+ case RawFunction::kImplicitGetter:
+ return "kImplicitGetter";
+ break;
+ case RawFunction::kImplicitSetter:
+ return "kImplicitSetter";
+ break;
+ case RawFunction::kImplicitStaticFinalGetter:
+ return "kImplicitStaticFinalGetter";
+ break;
+ case RawFunction::kStaticInitializer:
+ return "kStaticInitializer";
+ break;
+ case RawFunction::kMethodExtractor:
+ return "kMethodExtractor";
+ break;
+ case RawFunction::kNoSuchMethodDispatcher:
+ return "kNoSuchMethodDispatcher";
+ break;
+ case RawFunction::kInvokeFieldDispatcher:
+ return "kInvokeFieldDispatcher";
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
void Function::SetRedirectionType(const Type& type) const {
ASSERT(IsFactory());
Object& obj = Object::Handle(raw_ptr()->data_);
@@ -5619,11 +5874,31 @@
const char* internal_function_name = String::Handle(name()).ToCString();
const char* function_name =
String::Handle(QualifiedUserVisibleName()).ToCString();
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ Class& cls = Class::Handle(Owner());
+ ASSERT(!cls.IsNull());
+ Error& err = Error::Handle();
+ err ^= cls.EnsureIsFinalized(Isolate::Current());
+ ASSERT(err.IsNull());
+ intptr_t id = -1;
+ const char* selector = NULL;
+ if (IsNonImplicitClosureFunction()) {
+ id = cls.FindClosureIndex(*this);
+ selector = "closures";
+ } else if (IsImplicitClosureFunction()) {
+ id = cls.FindImplicitClosureFunctionIndex(*this);
+ selector = "implicit_closures";
+ } else if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher()) {
+ id = cls.FindInvocationDispatcherFunctionIndex(*this);
+ selector = "dispatchers";
+ } else {
+ id = cls.FindFunctionIndex(*this);
+ selector = "functions";
+ }
+ ASSERT(id >= 0);
+ intptr_t cid = cls.id();
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
+ jsobj.AddPropertyF("id", "classes/%" Pd "/%s/%" Pd "", cid, selector, id);
jsobj.AddProperty("name", internal_function_name);
jsobj.AddProperty("user_name", function_name);
if (ref) return;
@@ -5631,44 +5906,7 @@
jsobj.AddProperty("is_const", is_const());
jsobj.AddProperty("is_optimizable", is_optimizable());
jsobj.AddProperty("is_inlinable", IsInlineable());
- const char* kind_string = NULL;
- switch (kind()) {
- case RawFunction::kRegularFunction:
- kind_string = "regular";
- break;
- case RawFunction::kGetterFunction:
- kind_string = "getter";
- break;
- case RawFunction::kSetterFunction:
- kind_string = "setter";
- break;
- case RawFunction::kImplicitGetter:
- kind_string = "implicit getter";
- break;
- case RawFunction::kImplicitSetter:
- kind_string = "implicit setter";
- break;
- case RawFunction::kMethodExtractor:
- kind_string = "method extractor";
- break;
- case RawFunction::kNoSuchMethodDispatcher:
- kind_string = "no such method";
- break;
- case RawFunction::kClosureFunction:
- kind_string = "closure";
- break;
- case RawFunction::kConstructor:
- kind_string = "constructor";
- break;
- case RawFunction::kStaticInitializer:
- kind_string = "static initializer";
- break;
- case RawFunction::kImplicitStaticFinalGetter:
- kind_string = "static final getter";
- break;
- default:
- UNREACHABLE();
- }
+ const char* kind_string = Function::KindToCString(kind());
jsobj.AddProperty("kind", kind_string);
jsobj.AddProperty("unoptimized_code", Object::Handle(unoptimized_code()));
jsobj.AddProperty("usage_counter", usage_counter());
@@ -5952,10 +6190,12 @@
JSONObject jsobj(stream);
const char* internal_field_name = String::Handle(name()).ToCString();
const char* field_name = String::Handle(UserVisibleName()).ToCString();
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ Class& cls = Class::Handle(owner());
+ intptr_t id = cls.FindFieldIndex(*this);
+ ASSERT(id >= 0);
+ intptr_t cid = cls.id();
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
+ jsobj.AddPropertyF("id", "classes/%" Pd "/fields/%" Pd "", cid, id);
jsobj.AddProperty("name", internal_field_name);
jsobj.AddProperty("user_name", field_name);
if (is_static()) {
@@ -5965,7 +6205,7 @@
const Object& valueObj = Object::Handle(instance.GetField(*this));
jsobj.AddProperty("value", valueObj);
}
- Class& cls = Class::Handle(owner());
+
jsobj.AddProperty("owner", cls);
AbstractType& declared_type = AbstractType::Handle(type());
cls = declared_type.type_class();
@@ -7119,12 +7359,14 @@
void Script::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
const String& name = String::Handle(url());
+ ASSERT(!name.IsNull());
+ const String& encoded_url = String::Handle(String::EncodeURI(name));
+ ASSERT(!encoded_url.IsNull());
+ jsobj.AddPropertyF("id", "scripts/%s", encoded_url.ToCString());
jsobj.AddProperty("name", name.ToCString());
+ jsobj.AddProperty("user_name", name.ToCString());
jsobj.AddProperty("kind", GetKindAsCString());
if (ref) {
return;
@@ -8193,13 +8435,13 @@
void Library::PrintToJSONStream(JSONStream* stream, bool ref) const {
const char* library_name = String::Handle(name()).ToCString();
const char* library_url = String::Handle(url()).ToCString();
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ intptr_t id = index();
+ ASSERT(id >= 0);
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
+ jsobj.AddPropertyF("id", "libraries/%" Pd "", id);
jsobj.AddProperty("name", library_name);
- jsobj.AddProperty("url", library_url);
+ jsobj.AddProperty("user_name", library_url);
if (ref) return;
{
JSONArray jsarr(&jsobj, "classes");
@@ -9581,10 +9823,26 @@
}
-void Code::Disassemble() const {
+void Code::Disassemble(DisassemblyFormatter* formatter) const {
+ const bool fix_patch = CodePatcher::CodeIsPatchable(*this) &&
+ CodePatcher::IsEntryPatched(*this);
+ if (fix_patch) {
+ // The disassembler may choke on illegal instructions if the code has been
+ // patched, un-patch the code before disassembling and re-patch after.
+ CodePatcher::RestoreEntry(*this);
+ }
const Instructions& instr = Instructions::Handle(instructions());
uword start = instr.EntryPoint();
- Disassembler::Disassemble(start, start + instr.size(), comments());
+ if (formatter == NULL) {
+ Disassembler::Disassemble(start, start + instr.size(), comments());
+ } else {
+ Disassembler::Disassemble(start, start + instr.size(), formatter,
+ comments());
+ }
+ if (fix_patch) {
+ // Redo the patch.
+ CodePatcher::PatchEntry(*this);
+ }
}
@@ -9696,7 +9954,7 @@
// Check if object matches find condition.
-bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) {
+bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) const {
return RawInstructions::ContainsPC(obj, pc_);
}
@@ -9766,25 +10024,33 @@
void Code::PrintToJSONStream(JSONStream* stream, bool ref) const {
- ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
JSONObject jsobj(stream);
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddPropertyF("id", "code/%" Px "", EntryPoint());
+ jsobj.AddPropertyF("start", "%" Px "", EntryPoint());
+ jsobj.AddPropertyF("end", "%" Px "", EntryPoint() + Size());
+ Function& func = Function::Handle();
+ func ^= function();
+ ASSERT(!func.IsNull());
+ String& name = String::Handle();
+ ASSERT(!func.IsNull());
+ name ^= func.name();
+ const char* internal_function_name = name.ToCString();
+ jsobj.AddPropertyF("name", "%s%s", is_optimized() ? "*" : "",
+ internal_function_name);
+ name ^= func.QualifiedUserVisibleName();
+ const char* function_name = name.ToCString();
+ jsobj.AddPropertyF("user_name", "%s%s", is_optimized() ? "*" : "",
+ function_name);
if (ref) {
- jsobj.AddProperty("type", "@Code");
- jsobj.AddProperty("id", id);
return;
}
- jsobj.AddProperty("type", "Code");
- jsobj.AddProperty("id", id);
jsobj.AddProperty("is_optimized", is_optimized());
jsobj.AddProperty("is_alive", is_alive());
jsobj.AddProperty("function", Object::Handle(function()));
JSONArray jsarr(&jsobj, "disassembly");
DisassembleToJSONStream formatter(jsarr);
- const Instructions& instr = Instructions::Handle(instructions());
- uword start = instr.EntryPoint();
- Disassembler::Disassemble(start, start + instr.size(), &formatter,
- comments());
+ Disassemble(&formatter);
}
@@ -11477,7 +11743,7 @@
JSONObject jsobj(stream);
jsobj.AddProperty("type", JSONType(ref));
- jsobj.AddProperty("id", id);
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
Class& cls = Class::Handle(this->clazz());
jsobj.AddProperty("class", cls);
@@ -12320,6 +12586,7 @@
}
#endif
ASSERT(IsOld());
+ ASSERT(type_args.IsNull() || type_args.IsOld());
SetCanonical();
return this->raw();
}
@@ -14335,6 +14602,154 @@
}
+static bool IsPercent(int32_t c) {
+ return c == '%';
+}
+
+
+static bool IsHexCharacter(int32_t c) {
+ if (c >= '0' && c <= '9') {
+ return true;
+ }
+ if (c >= 'A' && c <= 'F') {
+ return true;
+ }
+ return false;
+}
+
+
+static bool IsURISafeCharacter(int32_t c) {
+ if ((c >= '0') && (c <= '9')) {
+ return true;
+ }
+ if ((c >= 'a') && (c <= 'z')) {
+ return true;
+ }
+ if ((c >= 'A') && (c <= 'Z')) {
+ return true;
+ }
+ return (c == '-') || (c == '_') || (c == '.') || (c == '~');
+}
+
+
+static int32_t GetHexCharacter(int32_t c) {
+ ASSERT(c >= 0);
+ ASSERT(c < 16);
+ const char* hex = "0123456789ABCDEF";
+ return hex[c];
+}
+
+
+static int32_t GetHexValue(int32_t c) {
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ }
+ if (c >= 'A' && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ UNREACHABLE();
+ return 0;
+}
+
+
+static int32_t MergeHexCharacters(int32_t c1, int32_t c2) {
+ return GetHexValue(c1) << 4 | GetHexValue(c2);
+}
+
+
+RawString* String::EncodeURI(const String& str) {
+ // URI encoding is only specified for one byte strings.
+ ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
+ intptr_t num_escapes = 0;
+ intptr_t len = str.Length();
+ {
+ CodePointIterator cpi(str);
+ while (cpi.Next()) {
+ int32_t code_point = cpi.Current();
+ if (!IsURISafeCharacter(code_point)) {
+ num_escapes += 2;
+ }
+ }
+ }
+ const String& dststr = String::Handle(
+ OneByteString::New(len + num_escapes, Heap::kNew));
+ {
+ intptr_t index = 0;
+ CodePointIterator cpi(str);
+ while (cpi.Next()) {
+ int32_t code_point = cpi.Current();
+ if (!IsURISafeCharacter(code_point)) {
+ OneByteString::SetCharAt(dststr, index, '%');
+ OneByteString::SetCharAt(dststr, index + 1,
+ GetHexCharacter(code_point >> 4));
+ OneByteString::SetCharAt(dststr, index + 2,
+ GetHexCharacter(code_point & 0xF));
+ index += 3;
+ } else {
+ OneByteString::SetCharAt(dststr, index, code_point);
+ index += 1;
+ }
+ }
+ }
+ return dststr.raw();
+}
+
+
+RawString* String::DecodeURI(const String& str) {
+ // URI encoding is only specified for one byte strings.
+ ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
+ CodePointIterator cpi(str);
+ intptr_t num_escapes = 0;
+ intptr_t len = str.Length();
+ {
+ CodePointIterator cpi(str);
+ while (cpi.Next()) {
+ int32_t code_point = cpi.Current();
+ if (IsPercent(code_point)) {
+ // Verify that the two characters following the % are hex digits.
+ if (!cpi.Next()) {
+ return str.raw();
+ }
+ int32_t code_point = cpi.Current();
+ if (!IsHexCharacter(code_point)) {
+ return str.raw();
+ }
+ if (!cpi.Next()) {
+ return str.raw();
+ }
+ code_point = cpi.Current();
+ if (!IsHexCharacter(code_point)) {
+ return str.raw();
+ }
+ num_escapes += 2;
+ }
+ }
+ }
+ ASSERT(len - num_escapes > 0);
+ const String& dststr = String::Handle(
+ OneByteString::New(len - num_escapes, Heap::kNew));
+ {
+ intptr_t index = 0;
+ CodePointIterator cpi(str);
+ while (cpi.Next()) {
+ int32_t code_point = cpi.Current();
+ if (IsPercent(code_point)) {
+ cpi.Next();
+ int32_t ch1 = cpi.Current();
+ cpi.Next();
+ int32_t ch2 = cpi.Current();
+ int32_t merged = MergeHexCharacters(ch1, ch2);
+ OneByteString::SetCharAt(dststr, index, merged);
+ } else {
+ OneByteString::SetCharAt(dststr, index, code_point);
+ }
+ index++;
+ }
+ }
+ return dststr.raw();
+}
+
+
RawString* String::NewFormatted(const char* format, ...) {
va_list args;
va_start(args, format);
« no previous file with comments | « dart/runtime/vm/object.h ('k') | dart/runtime/vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698