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

Unified Diff: vm/object.h

Issue 12052033: Added macros OBJECT_IMPLEMENTATION and FINAL_OBJECT_IMPLEMENTATION (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 7 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 | « vm/isolate.cc ('k') | vm/object.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vm/object.h
===================================================================
--- vm/object.h (revision 17436)
+++ vm/object.h (working copy)
@@ -39,21 +39,10 @@
#define CHECK_HANDLE()
#endif
-#define OBJECT_IMPLEMENTATION(object, super) \
+#define BASE_OBJECT_IMPLEMENTATION(object, super) \
public: /* NOLINT */ \
Raw##object* raw() const { return reinterpret_cast<Raw##object*>(raw_); } \
- void operator=(Raw##object* value) { \
- initializeHandle(this, value); \
- } \
bool Is##object() const { return true; } \
- void operator^=(RawObject* value) { \
- initializeHandle(this, value); \
- ASSERT(IsNull() || Is##object()); \
- } \
- void operator|=(RawObject* value) { \
- raw_ = value; \
- CHECK_HANDLE(); \
- } \
static object& Handle(Isolate* isolate, Raw##object* raw_ptr) { \
object* obj = \
reinterpret_cast<object*>(VMHandles::AllocateHandle(isolate)); \
@@ -88,6 +77,12 @@
initializeHandle(obj, raw_ptr); \
return *obj; \
} \
+ static object* ReadOnlyHandle(Isolate* isolate) { \
+ object* obj = reinterpret_cast<object*>( \
+ Dart::AllocateReadOnlyHandle()); \
+ initializeHandle(obj, object::null()); \
+ return obj; \
+ } \
static object& ZoneHandle() { \
return ZoneHandle(Isolate::Current(), object::null()); \
} \
@@ -119,8 +114,6 @@
} \
virtual const char* ToCString() const; \
static const ClassId kClassId = k##object##Cid; \
- protected: /* NOLINT */ \
- object() : super() {} \
private: /* NOLINT */ \
/* Initialize the handle based on the raw_ptr in the presence of null. */ \
static void initializeHandle(object* obj, RawObject* raw_ptr) { \
@@ -146,6 +139,19 @@
Snapshot::Kind); \
friend class SnapshotReader; \
+#define OBJECT_IMPLEMENTATION(object, super) \
+ public: /* NOLINT */ \
+ void operator=(Raw##object* value) { \
+ initializeHandle(this, value); \
+ } \
+ void operator^=(RawObject* value) { \
+ initializeHandle(this, value); \
+ ASSERT(IsNull() || Is##object()); \
+ } \
+ protected: /* NOLINT */ \
+ object() : super() {} \
+ BASE_OBJECT_IMPLEMENTATION(object, super) \
+
#define HEAP_OBJECT_IMPLEMENTATION(object, super) \
OBJECT_IMPLEMENTATION(object, super); \
Raw##object* raw_ptr() const { \
@@ -155,6 +161,27 @@
SNAPSHOT_READER_SUPPORT(object) \
friend class StackFrame; \
+// This macro is used to denote types that do not have a sub-type.
+#define FINAL_HEAP_OBJECT_IMPLEMENTATION(object, super) \
+ public: /* NOLINT */ \
+ void operator=(Raw##object* value) { \
+ raw_ = value; \
+ CHECK_HANDLE(); \
+ } \
+ void operator^=(RawObject* value) { \
+ raw_ = value; \
+ CHECK_HANDLE(); \
+ } \
+ private: /* NOLINT */ \
+ object() : super() {} \
+ BASE_OBJECT_IMPLEMENTATION(object, super) \
+ Raw##object* raw_ptr() const { \
+ ASSERT(raw() != null()); \
+ return raw()->ptr(); \
+ } \
+ SNAPSHOT_READER_SUPPORT(object) \
+ friend class StackFrame; \
+
class Object {
public:
virtual ~Object() { }
@@ -860,7 +887,7 @@
const AbstractTypeArguments& other_type_arguments,
Error* malformed_error) const;
- HEAP_OBJECT_IMPLEMENTATION(Class, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Class, Object);
friend class AbstractType;
friend class Instance;
friend class Object;
@@ -894,7 +921,7 @@
static RawUnresolvedClass* New();
- HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass, Object);
friend class Class;
};
@@ -1123,7 +1150,7 @@
void set_script(const Script& value) const;
static RawPatchClass* New();
- HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(PatchClass, Object);
friend class Class;
};
@@ -1601,7 +1628,7 @@
const AbstractTypeArguments& other_type_arguments,
Error* malformed_error) const;
- HEAP_OBJECT_IMPLEMENTATION(Function, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
friend class Class;
};
@@ -1636,7 +1663,7 @@
static RawClosureData* New();
- HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
friend class Class;
friend class Function;
friend class HeapProfiler;
@@ -1664,7 +1691,7 @@
static RawRedirectionData* New();
- HEAP_OBJECT_IMPLEMENTATION(RedirectionData, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(RedirectionData, Object);
friend class Class;
friend class Function;
friend class HeapProfiler;
@@ -1758,7 +1785,7 @@
}
static RawField* New();
- HEAP_OBJECT_IMPLEMENTATION(Field, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
friend class Class;
friend class HeapProfiler;
};
@@ -1782,7 +1809,7 @@
void set_literal(const String& literal) const;
void set_value(const Object& value) const;
- HEAP_OBJECT_IMPLEMENTATION(LiteralToken, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LiteralToken, Object);
friend class Class;
};
@@ -1860,7 +1887,7 @@
static RawTokenStream* New();
static void DataFinalizer(void *peer);
- HEAP_OBJECT_IMPLEMENTATION(TokenStream, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(TokenStream, Object);
friend class Class;
};
@@ -1911,7 +1938,7 @@
void set_tokens(const TokenStream& value) const;
static RawScript* New();
- HEAP_OBJECT_IMPLEMENTATION(Script, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Script, Object);
friend class Class;
};
@@ -2104,7 +2131,7 @@
bool import_core_lib);
RawObject* LookupEntry(const String& name, intptr_t *index) const;
- HEAP_OBJECT_IMPLEMENTATION(Library, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
friend class Class;
friend class Debugger;
friend class DictionaryIterator;
@@ -2141,7 +2168,7 @@
void set_num_imports(intptr_t value) const;
static RawLibraryPrefix* New();
- HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Object);
friend class Class;
friend class Isolate;
};
@@ -2166,7 +2193,7 @@
private:
static RawNamespace* New();
- HEAP_OBJECT_IMPLEMENTATION(Namespace, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Namespace, Object);
friend class Class;
};
@@ -2222,7 +2249,7 @@
// and links the two in a GC safe manner.
static RawInstructions* New(intptr_t size);
- HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
friend class Class;
friend class Code;
};
@@ -2258,7 +2285,7 @@
static RawLocalVarDescriptors* New(intptr_t num_variables);
private:
- HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors, Object);
friend class Class;
};
@@ -2356,7 +2383,7 @@
return reinterpret_cast<RawSmi**>(EntryAddr(index, entry_offset));
}
- HEAP_OBJECT_IMPLEMENTATION(PcDescriptors, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors, Object);
friend class Class;
};
@@ -2409,7 +2436,7 @@
bool GetBit(intptr_t bit_index) const;
void SetBit(intptr_t bit_index, bool value) const;
- HEAP_OBJECT_IMPLEMENTATION(Stackmap, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Stackmap, Object);
friend class BitmapBuilder;
friend class Class;
};
@@ -2455,7 +2482,7 @@
static const intptr_t kMaxHandlers = 1024 * 1024;
void set_handled_types_data(const Array& value) const;
- HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers, Object);
friend class Class;
};
@@ -2522,7 +2549,7 @@
void SetLength(intptr_t value) const;
- HEAP_OBJECT_IMPLEMENTATION(DeoptInfo, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(DeoptInfo, Object);
friend class Class;
};
@@ -2755,7 +2782,7 @@
// and links the two in a GC safe manner.
static RawCode* New(intptr_t pointer_offsets_length);
- HEAP_OBJECT_IMPLEMENTATION(Code, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
friend class Class;
};
@@ -2816,7 +2843,7 @@
raw_ptr()->num_variables_ = num_variables;
}
- HEAP_OBJECT_IMPLEMENTATION(Context, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Context, Object);
friend class Class;
};
@@ -2888,7 +2915,7 @@
return reinterpret_cast<RawContextScope::VariableDesc*>(raw_addr);
}
- HEAP_OBJECT_IMPLEMENTATION(ContextScope, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ContextScope, Object);
friend class Class;
};
@@ -3025,7 +3052,7 @@
intptr_t TestEntryLength() const;
void WriteSentinel() const;
- HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ICData, Object);
friend class Class;
};
@@ -3079,7 +3106,7 @@
static inline RawObject* GetTargetFunction(const Array& array,
intptr_t index);
- HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(MegamorphicCache, Object);
};
@@ -3123,7 +3150,7 @@
intptr_t TestEntryLength() const;
- HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache, Object);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache, Object);
friend class Class;
};
@@ -3157,7 +3184,7 @@
void set_message(const String& message) const;
static RawApiError* New();
- HEAP_OBJECT_IMPLEMENTATION(ApiError, Error);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ApiError, Error);
friend class Class;
};
@@ -3182,7 +3209,7 @@
void set_message(const String& message) const;
static RawLanguageError* New();
- HEAP_OBJECT_IMPLEMENTATION(LanguageError, Error);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LanguageError, Error);
friend class Class;
};
@@ -3213,7 +3240,7 @@
void set_exception(const Instance& exception) const;
void set_stacktrace(const Instance& stacktrace) const;
- HEAP_OBJECT_IMPLEMENTATION(UnhandledException, Error);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(UnhandledException, Error);
friend class Class;
};
@@ -3237,7 +3264,7 @@
private:
void set_message(const String& message) const;
- HEAP_OBJECT_IMPLEMENTATION(UnwindError, Error);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(UnwindError, Error);
friend class Class;
};
@@ -3736,7 +3763,7 @@
private:
void set_value(int64_t value) const;
- HEAP_OBJECT_IMPLEMENTATION(Mint, Integer);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Mint, Integer);
friend class Class;
};
@@ -3817,7 +3844,7 @@
static RawBigint* Allocate(intptr_t length, Heap::Space space = Heap::kNew);
- HEAP_OBJECT_IMPLEMENTATION(Bigint, Integer);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Bigint, Integer);
friend class BigintOperations;
friend class Class;
};
@@ -3855,7 +3882,7 @@
private:
void set_value(double value) const;
- HEAP_OBJECT_IMPLEMENTATION(Double, Number);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Double, Number);
friend class Class;
};
@@ -4108,7 +4135,7 @@
CallbackType new_symbol,
Snapshot::Kind kind);
- HEAP_OBJECT_IMPLEMENTATION(String, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
friend class Class;
friend class Symbols;
@@ -4470,7 +4497,7 @@
// New should only be called to initialize the two legal bool values.
static RawBool* New(bool value);
- HEAP_OBJECT_IMPLEMENTATION(Bool, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Bool, Instance);
friend class Class;
friend class Object; // To initialize the true and false values.
};
@@ -4574,7 +4601,7 @@
static RawImmutableArray* New(intptr_t len, Heap::Space space = Heap::kNew);
private:
- HEAP_OBJECT_IMPLEMENTATION(ImmutableArray, Array);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray, Array);
friend class Class;
};
@@ -4683,7 +4710,7 @@
static const int kDefaultInitialCapacity = 4;
- HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray, Instance);
friend class Array;
friend class Class;
};
@@ -4802,7 +4829,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Int8Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Int8Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -4854,7 +4881,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Uint8Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint8Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -4907,7 +4934,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Uint8ClampedArray, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint8ClampedArray, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -4959,7 +4986,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Int16Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Int16Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5011,7 +5038,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Uint16Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint16Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5063,7 +5090,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Int32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Int32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5115,7 +5142,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Uint32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5167,7 +5194,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Int64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Int64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5219,7 +5246,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Uint64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Uint64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5271,7 +5298,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Float32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Float32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5323,7 +5350,7 @@
return reinterpret_cast<uint8_t*>(&raw_ptr()->data_) + byte_offset;
}
- HEAP_OBJECT_IMPLEMENTATION(Float64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Float64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5381,7 +5408,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalInt8Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalInt8Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5459,7 +5486,8 @@
Heap::Space space = Heap::kNew);
private:
- HEAP_OBJECT_IMPLEMENTATION(ExternalUint8ClampedArray, ExternalUint8Array);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalUint8ClampedArray,
+ ExternalUint8Array);
friend class Class;
};
@@ -5516,7 +5544,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalInt16Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalInt16Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5574,7 +5602,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalUint16Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalUint16Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5632,7 +5660,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalInt32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalInt32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5690,7 +5718,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalUint32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalUint32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5748,7 +5776,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalInt64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalInt64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5806,7 +5834,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalUint64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalUint64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5864,7 +5892,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5922,7 +5950,7 @@
raw_ptr()->external_data_ = data;
}
- HEAP_OBJECT_IMPLEMENTATION(ExternalFloat64Array, ByteArray);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat64Array, ByteArray);
friend class ByteArray;
friend class Class;
};
@@ -5931,7 +5959,7 @@
// DartFunction represents the abstract Dart class 'Function'.
class DartFunction : public Instance {
private:
- HEAP_OBJECT_IMPLEMENTATION(DartFunction, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(DartFunction, Instance);
friend class Class;
friend class Instance;
};
@@ -6036,7 +6064,7 @@
void set_code_array(const Array& code_array) const;
void set_pc_offset_array(const Array& pc_offset_array) const;
- HEAP_OBJECT_IMPLEMENTATION(Stacktrace, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Stacktrace, Instance);
friend class Class;
};
@@ -6116,7 +6144,7 @@
raw_ptr()->data_length_ = Smi::New(value);
}
- HEAP_OBJECT_IMPLEMENTATION(JSRegExp, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(JSRegExp, Instance);
friend class Class;
};
@@ -6151,7 +6179,7 @@
}
private:
- HEAP_OBJECT_IMPLEMENTATION(WeakProperty, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakProperty, Instance);
friend class Class;
};
« no previous file with comments | « vm/isolate.cc ('k') | vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698