Commit 6a3921fc authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Keep natives source code in external strings instead of putting

it in regular flat strings that are part of the snapshot.
After this change we don't need libraries-empty.cc any more.  In
this change libraries-empty.cc is just a the same as libraries.cc
and the scons build builds it but does not use it.  We can move
in stages to a situation where it is not generated at all for all
the build systems that we have.
Review URL: http://codereview.chromium.org/360050

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3238 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 321bed24
...@@ -264,7 +264,6 @@ def ConfigureObjectFiles(): ...@@ -264,7 +264,6 @@ def ConfigureObjectFiles():
else: else:
snapshot_cc = Command('snapshot.cc', [], []) snapshot_cc = Command('snapshot.cc', [], [])
snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.']) snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
libraries_obj = context.ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
else: else:
snapshot_obj = empty_snapshot_obj snapshot_obj = empty_snapshot_obj
library_objs = [non_snapshot_files, libraries_obj, snapshot_obj] library_objs = [non_snapshot_files, libraries_obj, snapshot_obj]
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "global-handles.h" #include "global-handles.h"
#include "macro-assembler.h" #include "macro-assembler.h"
#include "natives.h" #include "natives.h"
#include "snapshot.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -92,14 +93,34 @@ class SourceCodeCache BASE_EMBEDDED { ...@@ -92,14 +93,34 @@ class SourceCodeCache BASE_EMBEDDED {
static SourceCodeCache natives_cache(Script::TYPE_NATIVE); static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION); static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
// This is for delete, not delete[].
static List<char*>* delete_these_non_arrays_on_tear_down = NULL;
Handle<String> Bootstrapper::NativesSourceLookup(int index) { Handle<String> Bootstrapper::NativesSourceLookup(int index) {
ASSERT(0 <= index && index < Natives::GetBuiltinsCount()); ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
if (Heap::natives_source_cache()->get(index)->IsUndefined()) { if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
Handle<String> source_code = if (!Snapshot::IsEnabled || FLAG_new_snapshot) {
Factory::NewStringFromAscii(Natives::GetScriptSource(index)); if (delete_these_non_arrays_on_tear_down == NULL) {
Heap::natives_source_cache()->set(index, *source_code); delete_these_non_arrays_on_tear_down = new List<char*>(2);
}
// We can use external strings for the natives.
NativesExternalStringResource* resource =
new NativesExternalStringResource(
Natives::GetScriptSource(index).start());
// The resources are small objects and we only make a fixed number of
// them, but lets clean them up on exit for neatness.
delete_these_non_arrays_on_tear_down->
Add(reinterpret_cast<char*>(resource));
Handle<String> source_code =
Factory::NewExternalStringFromAscii(resource);
Heap::natives_source_cache()->set(index, *source_code);
} else {
// Old snapshot code can't cope with external strings at all.
Handle<String> source_code =
Factory::NewStringFromAscii(Natives::GetScriptSource(index));
Heap::natives_source_cache()->set(index, *source_code);
}
} }
Handle<Object> cached_source(Heap::natives_source_cache()->get(index)); Handle<Object> cached_source(Heap::natives_source_cache()->get(index));
return Handle<String>::cast(cached_source); return Handle<String>::cast(cached_source);
...@@ -125,6 +146,16 @@ void Bootstrapper::Initialize(bool create_heap_objects) { ...@@ -125,6 +146,16 @@ void Bootstrapper::Initialize(bool create_heap_objects) {
void Bootstrapper::TearDown() { void Bootstrapper::TearDown() {
if (delete_these_non_arrays_on_tear_down != NULL) {
int len = delete_these_non_arrays_on_tear_down->length();
ASSERT(len < 20); // Don't use this mechanism for unbounded allocations.
for (int i = 0; i < len; i++) {
delete delete_these_non_arrays_on_tear_down->at(i);
}
delete delete_these_non_arrays_on_tear_down;
delete_these_non_arrays_on_tear_down = NULL;
}
natives_cache.Initialize(false); // Yes, symmetrical natives_cache.Initialize(false); // Yes, symmetrical
extensions_cache.Initialize(false); extensions_cache.Initialize(false);
} }
......
...@@ -76,6 +76,25 @@ class Bootstrapper : public AllStatic { ...@@ -76,6 +76,25 @@ class Bootstrapper : public AllStatic {
static void FreeThreadResources(); static void FreeThreadResources();
}; };
class NativesExternalStringResource
: public v8::String::ExternalAsciiStringResource {
public:
explicit NativesExternalStringResource(const char* source)
: data_(source), length_(strlen(source)) { }
const char* data() const {
return data_;
}
size_t length() const {
return length_;
}
private:
const char* data_;
size_t length_;
};
}} // namespace v8::internal }} // namespace v8::internal
#endif // V8_BOOTSTRAPPER_H_ #endif // V8_BOOTSTRAPPER_H_
...@@ -163,11 +163,6 @@ bool Object::IsConsString() { ...@@ -163,11 +163,6 @@ bool Object::IsConsString() {
} }
#ifdef DEBUG
// These are for cast checks. If you need one of these in release
// mode you should consider using a StringShape before moving it out
// of the ifdef
bool Object::IsSeqString() { bool Object::IsSeqString() {
if (!IsString()) return false; if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential(); return StringShape(String::cast(this)).IsSequential();
...@@ -214,9 +209,6 @@ bool Object::IsSlicedString() { ...@@ -214,9 +209,6 @@ bool Object::IsSlicedString() {
} }
#endif // DEBUG
StringShape::StringShape(String* str) StringShape::StringShape(String* str)
: type_(str->map()->instance_type()) { : type_(str->map()->instance_type()) {
set_valid(); set_valid();
......
...@@ -1138,6 +1138,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size, ...@@ -1138,6 +1138,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case kSlicedStringTag: case kSlicedStringTag:
reinterpret_cast<SlicedString*>(this)->SlicedStringIterateBody(v); reinterpret_cast<SlicedString*>(this)->SlicedStringIterateBody(v);
break; break;
case kExternalStringTag:
if ((type & kStringEncodingMask) == kAsciiStringTag) {
reinterpret_cast<ExternalAsciiString*>(this)->
ExternalAsciiStringIterateBody(v);
} else {
reinterpret_cast<ExternalTwoByteString*>(this)->
ExternalTwoByteStringIterateBody(v);
}
break;
} }
return; return;
} }
...@@ -4146,13 +4155,13 @@ void String::ReadBlockIntoBuffer(String* input, ...@@ -4146,13 +4155,13 @@ void String::ReadBlockIntoBuffer(String* input,
return; return;
case kExternalStringTag: case kExternalStringTag:
if (input->IsAsciiRepresentation()) { if (input->IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)-> ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else { } else {
ExternalTwoByteString::cast(input)-> ExternalTwoByteString::cast(input)->
ExternalTwoByteStringReadBlockIntoBuffer(rbb, ExternalTwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr, offset_ptr,
max_chars); max_chars);
} }
return; return;
default: default:
...@@ -4398,6 +4407,23 @@ void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) { ...@@ -4398,6 +4407,23 @@ void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
IteratePointer(v, kBufferOffset); IteratePointer(v, kBufferOffset);
} }
#define FIELD_ADDR(p, offset) \
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalAsciiStringResource Resource;
v->VisitExternalAsciiString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalStringResource Resource;
v->VisitExternalTwoByteString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
#undef FIELD_ADDR
uint16_t SlicedString::SlicedStringGet(int index) { uint16_t SlicedString::SlicedStringGet(int index) {
ASSERT(index >= 0 && index < this->length()); ASSERT(index >= 0 && index < this->length());
......
...@@ -790,7 +790,6 @@ class Object BASE_EMBEDDED { ...@@ -790,7 +790,6 @@ class Object BASE_EMBEDDED {
inline bool IsHeapNumber(); inline bool IsHeapNumber();
inline bool IsString(); inline bool IsString();
inline bool IsSymbol(); inline bool IsSymbol();
#ifdef DEBUG
// See objects-inl.h for more details // See objects-inl.h for more details
inline bool IsSeqString(); inline bool IsSeqString();
inline bool IsSlicedString(); inline bool IsSlicedString();
...@@ -799,7 +798,6 @@ class Object BASE_EMBEDDED { ...@@ -799,7 +798,6 @@ class Object BASE_EMBEDDED {
inline bool IsExternalAsciiString(); inline bool IsExternalAsciiString();
inline bool IsSeqTwoByteString(); inline bool IsSeqTwoByteString();
inline bool IsSeqAsciiString(); inline bool IsSeqAsciiString();
#endif // DEBUG
inline bool IsConsString(); inline bool IsConsString();
inline bool IsNumber(); inline bool IsNumber();
...@@ -4438,6 +4436,9 @@ class ExternalAsciiString: public ExternalString { ...@@ -4438,6 +4436,9 @@ class ExternalAsciiString: public ExternalString {
// Casting. // Casting.
static inline ExternalAsciiString* cast(Object* obj); static inline ExternalAsciiString* cast(Object* obj);
// Garbage collection support.
void ExternalAsciiStringIterateBody(ObjectVisitor* v);
// Support for StringInputBuffer. // Support for StringInputBuffer.
const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining, const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
unsigned* offset, unsigned* offset,
...@@ -4473,6 +4474,9 @@ class ExternalTwoByteString: public ExternalString { ...@@ -4473,6 +4474,9 @@ class ExternalTwoByteString: public ExternalString {
// Casting. // Casting.
static inline ExternalTwoByteString* cast(Object* obj); static inline ExternalTwoByteString* cast(Object* obj);
// Garbage collection support.
void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
// Support for StringInputBuffer. // Support for StringInputBuffer.
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer, void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr, unsigned* offset_ptr,
...@@ -5104,6 +5108,12 @@ class ObjectVisitor BASE_EMBEDDED { ...@@ -5104,6 +5108,12 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits a runtime entry in the instruction stream. // Visits a runtime entry in the instruction stream.
virtual void VisitRuntimeEntry(RelocInfo* rinfo) {} virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
// Visits the resource of an ASCII or two-byte string.
virtual void VisitExternalAsciiString(
v8::String::ExternalAsciiStringResource** resource) {}
virtual void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) {}
// Visits a debug call target in the instruction stream. // Visits a debug call target in the instruction stream.
virtual void VisitDebugTarget(RelocInfo* rinfo); virtual void VisitDebugTarget(RelocInfo* rinfo);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "stub-cache.h" #include "stub-cache.h"
#include "v8threads.h" #include "v8threads.h"
#include "top.h" #include "top.h"
#include "bootstrapper.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -2062,6 +2063,14 @@ void Deserializer2::ReadChunk(Object** current, ...@@ -2062,6 +2063,14 @@ void Deserializer2::ReadChunk(Object** current,
pages_[space].Add(last_object_address_); pages_[space].Add(last_object_address_);
break; break;
} }
case NATIVES_STRING_RESOURCE: {
int index = source_->Get();
Vector<const char> source_vector = Natives::GetScriptSource(index);
NativesExternalStringResource* resource =
new NativesExternalStringResource(source_vector.start());
*current++ = reinterpret_cast<Object*>(resource);
break;
}
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -2253,7 +2262,7 @@ void Serializer2::ObjectSerializer::VisitPointers(Object** start, ...@@ -2253,7 +2262,7 @@ void Serializer2::ObjectSerializer::VisitPointers(Object** start,
Object** current = start; Object** current = start;
while (current < end) { while (current < end) {
while (current < end && (*current)->IsSmi()) current++; while (current < end && (*current)->IsSmi()) current++;
OutputRawData(reinterpret_cast<Address>(current)); if (current < end) OutputRawData(reinterpret_cast<Address>(current));
while (current < end && !(*current)->IsSmi()) { while (current < end && !(*current)->IsSmi()) {
serializer_->SerializeObject(*current, TAGGED_REPRESENTATION); serializer_->SerializeObject(*current, TAGGED_REPRESENTATION);
...@@ -2300,6 +2309,33 @@ void Serializer2::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { ...@@ -2300,6 +2309,33 @@ void Serializer2::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
} }
void Serializer2::ObjectSerializer::VisitExternalAsciiString(
v8::String::ExternalAsciiStringResource** resource_pointer) {
Address references_start = reinterpret_cast<Address>(resource_pointer);
OutputRawData(references_start);
for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
// Use raw_unchecked when maps are munged.
Object* source = Heap::raw_unchecked_natives_source_cache()->get(i);
if (!source->IsUndefined()) {
// Don't use cast when maps are munged.
ExternalAsciiString* string =
reinterpret_cast<ExternalAsciiString*>(source);
typedef v8::String::ExternalAsciiStringResource Resource;
Resource* resource = string->resource();
if (resource == *resource_pointer) {
sink_->Put(NATIVES_STRING_RESOURCE, "NativesStringResource");
sink_->PutSection(i, "NativesStringResourceEnd");
bytes_processed_so_far_ += sizeof(resource);
return;
}
}
}
// One of the strings in the natives cache should match the resource. We
// can't serialize any other kinds of external strings.
UNREACHABLE();
}
void Serializer2::ObjectSerializer::OutputRawData(Address up_to) { void Serializer2::ObjectSerializer::OutputRawData(Address up_to) {
Address object_start = object_->address(); Address object_start = object_->address();
int up_to_offset = up_to - object_start; int up_to_offset = up_to - object_start;
......
...@@ -441,7 +441,8 @@ class SerDes: public GenericDeserializer { ...@@ -441,7 +441,8 @@ class SerDes: public GenericDeserializer {
EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35, EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35,
SYNCHRONIZE = 36, SYNCHRONIZE = 36,
START_NEW_PAGE_SERIALIZATION = 37, START_NEW_PAGE_SERIALIZATION = 37,
// Free: 38-47. NATIVES_STRING_RESOURCE = 38,
// Free: 39-47.
BACKREF_SERIALIZATION = 48, BACKREF_SERIALIZATION = 48,
// One per space, must be kSpaceMask aligned. // One per space, must be kSpaceMask aligned.
// Free: 57-63. // Free: 57-63.
...@@ -567,6 +568,14 @@ class Serializer2 : public SerDes { ...@@ -567,6 +568,14 @@ class Serializer2 : public SerDes {
void VisitExternalReferences(Address* start, Address* end); void VisitExternalReferences(Address* start, Address* end);
void VisitCodeTarget(RelocInfo* target); void VisitCodeTarget(RelocInfo* target);
void VisitRuntimeEntry(RelocInfo* reloc); void VisitRuntimeEntry(RelocInfo* reloc);
// Used for seralizing the external strings that hold the natives source.
void VisitExternalAsciiString(
v8::String::ExternalAsciiStringResource** resource);
// We can't serialize a heap with external two byte strings.
void VisitExternalTwoByteString(
v8::String::ExternalStringResource** resource) {
UNREACHABLE();
}
private: private:
void OutputRawData(Address up_to); void OutputRawData(Address up_to);
......
...@@ -35,9 +35,9 @@ test-api/ApplyInterruption: PASS || TIMEOUT ...@@ -35,9 +35,9 @@ test-api/ApplyInterruption: PASS || TIMEOUT
# This is about to go away anyway since new snapshot code is on the way. # This is about to go away anyway since new snapshot code is on the way.
test-serialize/Deserialize: FAIL test-serialize/Deserialize: FAIL
test-serialize/DeserializeAndRunScript: FAIL test-serialize/DeserializeAndRunScript: FAIL || CRASH
test-serialize/DeserializeNatives: FAIL test-serialize/DeserializeNatives: FAIL || CRASH
test-serialize/DeserializeExtensions: FAIL test-serialize/DeserializeExtensions: FAIL || CRASH
# These tests always fail. They are here to test test.py. If # These tests always fail. They are here to test test.py. If
# they don't fail then test.py has failed. # they don't fail then test.py has failed.
......
...@@ -301,7 +301,7 @@ def JS2C(source, target, env): ...@@ -301,7 +301,7 @@ def JS2C(source, target, env):
else: else:
ids.append((id, len(lines))) ids.append((id, len(lines)))
source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data }) source_lines.append(SOURCE_DECLARATION % { 'id': id, 'data': data })
source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': 0 }) source_lines_empty.append(SOURCE_DECLARATION % { 'id': id, 'data': data })
# Build delay support functions # Build delay support functions
get_index_cases = [ ] get_index_cases = [ ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment