📄 objects.cc.svn-base
字号:
ASSERT(!value->IsTheHole() || result->IsReadOnly()); return value->IsTheHole() ? Heap::undefined_value() : value; case CONSTANT_FUNCTION: return result->GetConstantFunction(); case CALLBACKS: return GetPropertyWithCallback(receiver, result->GetCallbackObject(), name, holder); case INTERCEPTOR: { JSObject* recvr = JSObject::cast(receiver); return holder->GetPropertyWithInterceptor(recvr, name, attributes); } default: UNREACHABLE(); return NULL; }}Object* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { // Non-JS objects do not have integer indexed properties. if (!IsJSObject()) return Heap::undefined_value(); return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver), index);}Object* Object::GetPrototype() { // The object is either a number, a string, a boolean, or a real JS object. if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); Context* context = Top::context()->global_context(); if (IsNumber()) return context->number_function()->instance_prototype(); if (IsString()) return context->string_function()->instance_prototype(); if (IsBoolean()) { return context->boolean_function()->instance_prototype(); } else { return Heap::null_value(); }}void Object::ShortPrint() { HeapStringAllocator allocator; StringStream accumulator(&allocator); ShortPrint(&accumulator); accumulator.OutputToStdOut();}void Object::ShortPrint(StringStream* accumulator) { if (IsSmi()) { Smi::cast(this)->SmiPrint(accumulator); } else if (IsFailure()) { Failure::cast(this)->FailurePrint(accumulator); } else { HeapObject::cast(this)->HeapObjectShortPrint(accumulator); }}void Smi::SmiPrint() { PrintF("%d", value());}void Smi::SmiPrint(StringStream* accumulator) { accumulator->Add("%d", value());}void Failure::FailurePrint(StringStream* accumulator) { accumulator->Add("Failure(%d)", value());}void Failure::FailurePrint() { PrintF("Failure(%d)", value());}Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) { ASSERT((space & ~kSpaceTagMask) == 0); int requested = requested_bytes >> kObjectAlignmentBits; int value = (requested << kSpaceTagSize) | space; // We can't very well allocate a heap number in this situation, and if the // requested memory is so large it seems reasonable to say that this is an // out of memory situation. This fixes a crash in // js1_5/Regress/regress-303213.js. if (value >> kSpaceTagSize != requested || !Smi::IsValid(value) || value != ((value << kFailureTypeTagSize) >> kFailureTypeTagSize) || !Smi::IsValid(value << kFailureTypeTagSize)) { Top::context()->mark_out_of_memory(); return Failure::OutOfMemoryException(); } return Construct(RETRY_AFTER_GC, value);}// Should a word be prefixed by 'a' or 'an' in order to read naturally in// English? Returns false for non-ASCII or words that don't start with// a capital letter. The a/an rule follows pronunciation in English.// We don't use the BBC's overcorrect "an historic occasion" though if// you speak a dialect you may well say "an 'istoric occasion".static bool AnWord(String* str) { if (str->length() == 0) return false; // a nothing int c0 = str->Get(0); int c1 = str->length() > 1 ? str->Get(1) : 0; if (c0 == 'U') { if (c1 > 'Z') { return true; // an Umpire, but a UTF8String, a U } } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') { return true; // an Ape, an ABCBook } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || c0 == 'S' || c0 == 'X')) { return true; // an MP3File, an M } return false;}Object* String::Flatten() {#ifdef DEBUG // Do not attempt to flatten in debug mode when allocation is not // allowed. This is to avoid an assertion failure when allocating. // Flattening strings is the only case where we always allow // allocation because no GC is performed if the allocation fails. if (!Heap::IsAllocationAllowed()) return this;#endif switch (representation_tag()) { case kSlicedStringTag: { SlicedString* ss = SlicedString::cast(this); // The SlicedString constructor should ensure that there are no // SlicedStrings that are constructed directly on top of other // SlicedStrings. ASSERT(!ss->buffer()->IsSlicedString()); Object* ok = String::cast(ss->buffer())->Flatten(); if (ok->IsFailure()) return ok; return this; } case kConsStringTag: { ConsString* cs = ConsString::cast(this); if (String::cast(cs->second())->length() == 0) { return this; } // There's little point in putting the flat string in new space if the // cons string is in old space. It can never get GCed until there is // an old space GC. PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; Object* object = IsAscii() ? Heap::AllocateRawAsciiString(length(), tenure) : Heap::AllocateRawTwoByteString(length(), tenure); if (object->IsFailure()) return object; String* result = String::cast(object); Flatten(this, result, 0, length(), 0); cs->set_first(result); cs->set_second(Heap::empty_string()); return this; } default: return this; }}void String::StringShortPrint(StringStream* accumulator) { int len = length(); if (len > kMaxMediumStringSize) { accumulator->Add("<Very long string[%u]>", len); return; } if (!LooksValid()) { accumulator->Add("<Invalid String>"); return; } StringInputBuffer buf(this); bool truncated = false; if (len > kMaxShortPrintLength) { len = kMaxShortPrintLength; truncated = true; } bool ascii = true; for (int i = 0; i < len; i++) { int c = buf.GetNext(); if (c < 32 || c >= 127) { ascii = false; } } buf.Reset(this); if (ascii) { accumulator->Add("<String[%u]: ", length()); for (int i = 0; i < len; i++) { accumulator->Put(buf.GetNext()); } accumulator->Put('>'); } else { // Backslash indicates that the string contains control // characters and that backslashes are therefore escaped. accumulator->Add("<String[%u]\\: ", length()); for (int i = 0; i < len; i++) { int c = buf.GetNext(); if (c == '\n') { accumulator->Add("\\n"); } else if (c == '\r') { accumulator->Add("\\r"); } else if (c == '\\') { accumulator->Add("\\\\"); } else if (c < 32 || c > 126) { accumulator->Add("\\x%02x", c); } else { accumulator->Put(c); } } if (truncated) { accumulator->Put('.'); accumulator->Put('.'); accumulator->Put('.'); } accumulator->Put('>'); } return;}void JSObject::JSObjectShortPrint(StringStream* accumulator) { switch (map()->instance_type()) { case JS_ARRAY_TYPE: { double length = JSArray::cast(this)->length()->Number(); accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length)); break; } case JS_REGEXP_TYPE: { accumulator->Add("<JS RegExp>"); break; } case JS_FUNCTION_TYPE: { Object* fun_name = JSFunction::cast(this)->shared()->name(); bool printed = false; if (fun_name->IsString()) { String* str = String::cast(fun_name); if (str->length() > 0) { accumulator->Add("<JS Function "); accumulator->Put(str); accumulator->Put('>'); printed = true; } } if (!printed) { accumulator->Add("<JS Function>"); } break; } // All other JSObjects are rather similar to each other (JSObject, // JSGlobalObject, JSUndetectableObject, JSValue). default: { Object* constructor = map()->constructor(); bool printed = false; if (constructor->IsHeapObject() && !Heap::Contains(HeapObject::cast(constructor))) { accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); } else { bool global_object = IsJSGlobalObject(); if (constructor->IsJSFunction()) { if (!Heap::Contains(JSFunction::cast(constructor)->shared())) { accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); } else { Object* constructor_name = JSFunction::cast(constructor)->shared()->name(); if (constructor_name->IsString()) { String* str = String::cast(constructor_name); if (str->length() > 0) { bool vowel = AnWord(str); accumulator->Add("<%sa%s ", global_object ? "JS Global Object: " : "", vowel ? "n" : ""); accumulator->Put(str); accumulator->Put('>'); printed = true; } } } } if (!printed) { accumulator->Add("<JS %sObject", global_object ? "Global " : ""); } } if (IsJSValue()) { accumulator->Add(" value = "); JSValue::cast(this)->value()->ShortPrint(accumulator); } accumulator->Put('>'); break; } }}void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { // if (!Heap::InNewSpace(this)) PrintF("*", this); if (!Heap::Contains(this)) { accumulator->Add("!!!INVALID POINTER!!!"); return; } if (!Heap::Contains(map())) { accumulator->Add("!!!INVALID MAP!!!"); return; } accumulator->Add("%p ", this); if (IsString()) { String::cast(this)->StringShortPrint(accumulator); return; } if (IsJSObject()) { JSObject::cast(this)->JSObjectShortPrint(accumulator); return; } switch (map()->instance_type()) { case MAP_TYPE: accumulator->Add("<Map>"); break; case FIXED_ARRAY_TYPE: accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); break; case BYTE_ARRAY_TYPE: accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); break; case SHARED_FUNCTION_INFO_TYPE: accumulator->Add("<SharedFunctionInfo>"); break;#define MAKE_STRUCT_CASE(NAME, Name, name) \ case NAME##_TYPE: \ accumulator->Add(#Name); \ break; STRUCT_LIST(MAKE_STRUCT_CASE)#undef MAKE_STRUCT_CASE case CODE_TYPE: accumulator->Add("<Code>"); break; case ODDBALL_TYPE: { if (IsUndefined()) accumulator->Add("<undefined>"); else if (IsTheHole()) accumulator->Add("<the hole>"); else if (IsNull()) accumulator->Add("<null>"); else if (IsTrue()) accumulator->Add("<true>"); else if (IsFalse()) accumulator->Add("<false>"); else accumulator->Add("<Odd Oddball>"); break; } case HEAP_NUMBER_TYPE: accumulator->Add("<Number: "); HeapNumber::cast(this)->HeapNumberPrint(accumulator); accumulator->Put('>'); break; case PROXY_TYPE: accumulator->Add("<Proxy>"); break; default: accumulator->Add("<Other heap object (%d)>", map()->instance_type()); break; }}int HeapObject::SlowSizeFromMap(Map* map) { // Avoid calling functions such as FixedArray::cast during GC, which // read map pointer of this object again.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -