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():
else:
snapshot_cc = Command('snapshot.cc', [], [])
snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
libraries_obj = context.ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
else:
snapshot_obj = empty_snapshot_obj
library_objs = [non_snapshot_files, libraries_obj, snapshot_obj]
......
......@@ -36,6 +36,7 @@
#include "global-handles.h"
#include "macro-assembler.h"
#include "natives.h"
#include "snapshot.h"
namespace v8 {
namespace internal {
......@@ -92,14 +93,34 @@ class SourceCodeCache BASE_EMBEDDED {
static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
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) {
ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
Handle<String> source_code =
Factory::NewStringFromAscii(Natives::GetScriptSource(index));
Heap::natives_source_cache()->set(index, *source_code);
if (!Snapshot::IsEnabled || FLAG_new_snapshot) {
if (delete_these_non_arrays_on_tear_down == NULL) {
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));
return Handle<String>::cast(cached_source);
......@@ -125,6 +146,16 @@ void Bootstrapper::Initialize(bool create_heap_objects) {
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
extensions_cache.Initialize(false);
}
......
......@@ -76,6 +76,25 @@ class Bootstrapper : public AllStatic {
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
#endif // V8_BOOTSTRAPPER_H_
......@@ -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() {
if (!IsString()) return false;
return StringShape(String::cast(this)).IsSequential();
......@@ -214,9 +209,6 @@ bool Object::IsSlicedString() {
}
#endif // DEBUG
StringShape::StringShape(String* str)
: type_(str->map()->instance_type()) {
set_valid();
......
......@@ -1138,6 +1138,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case kSlicedStringTag:
reinterpret_cast<SlicedString*>(this)->SlicedStringIterateBody(v);
break;
case kExternalStringTag:
if ((type & kStringEncodingMask) == kAsciiStringTag) {
reinterpret_cast<ExternalAsciiString*>(this)->
ExternalAsciiStringIterateBody(v);
} else {
reinterpret_cast<ExternalTwoByteString*>(this)->
ExternalTwoByteStringIterateBody(v);
}
break;
}
return;
}
......@@ -4146,13 +4155,13 @@ void String::ReadBlockIntoBuffer(String* input,
return;
case kExternalStringTag:
if (input->IsAsciiRepresentation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
ExternalTwoByteString::cast(input)->
ExternalTwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
ExternalTwoByteString::cast(input)->
ExternalTwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
}
return;
default:
......@@ -4398,6 +4407,23 @@ void SlicedString::SlicedStringIterateBody(ObjectVisitor* v) {
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) {
ASSERT(index >= 0 && index < this->length());
......
......@@ -790,7 +790,6 @@ class Object BASE_EMBEDDED {
inline bool IsHeapNumber();
inline bool IsString();
inline bool IsSymbol();
#ifdef DEBUG
// See objects-inl.h for more details
inline bool IsSeqString();
inline bool IsSlicedString();
......@@ -799,7 +798,6 @@ class Object BASE_EMBEDDED {
inline bool IsExternalAsciiString();
inline bool IsSeqTwoByteString();
inline bool IsSeqAsciiString();
#endif // DEBUG
inline bool IsConsString();
inline bool IsNumber();
......@@ -4438,6 +4436,9 @@ class ExternalAsciiString: public ExternalString {
// Casting.
static inline ExternalAsciiString* cast(Object* obj);
// Garbage collection support.
void ExternalAsciiStringIterateBody(ObjectVisitor* v);
// Support for StringInputBuffer.
const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
unsigned* offset,
......@@ -4473,6 +4474,9 @@ class ExternalTwoByteString: public ExternalString {
// Casting.
static inline ExternalTwoByteString* cast(Object* obj);
// Garbage collection support.
void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
// Support for StringInputBuffer.
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,
......@@ -5104,6 +5108,12 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits a runtime entry in the instruction stream.
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.
virtual void VisitDebugTarget(RelocInfo* rinfo);
......
......@@ -39,6 +39,7 @@
#include "stub-cache.h"
#include "v8threads.h"
#include "top.h"
#include "bootstrapper.h"
namespace v8 {
namespace internal {
......@@ -2062,6 +2063,14 @@ void Deserializer2::ReadChunk(Object** current,
pages_[space].Add(last_object_address_);
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:
UNREACHABLE();
}
......@@ -2253,7 +2262,7 @@ void Serializer2::ObjectSerializer::VisitPointers(Object** start,
Object** current = start;
while (current < end) {
while (current < end && (*current)->IsSmi()) current++;
OutputRawData(reinterpret_cast<Address>(current));
if (current < end) OutputRawData(reinterpret_cast<Address>(current));
while (current < end && !(*current)->IsSmi()) {
serializer_->SerializeObject(*current, TAGGED_REPRESENTATION);
......@@ -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) {
Address object_start = object_->address();
int up_to_offset = up_to - object_start;
......
......@@ -441,7 +441,8 @@ class SerDes: public GenericDeserializer {
EXTERNAL_BRANCH_TARGET_SERIALIZATION = 35,
SYNCHRONIZE = 36,
START_NEW_PAGE_SERIALIZATION = 37,
// Free: 38-47.
NATIVES_STRING_RESOURCE = 38,
// Free: 39-47.
BACKREF_SERIALIZATION = 48,
// One per space, must be kSpaceMask aligned.
// Free: 57-63.
......@@ -567,6 +568,14 @@ class Serializer2 : public SerDes {
void VisitExternalReferences(Address* start, Address* end);
void VisitCodeTarget(RelocInfo* target);
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:
void OutputRawData(Address up_to);
......
......@@ -35,9 +35,9 @@ test-api/ApplyInterruption: PASS || TIMEOUT
# This is about to go away anyway since new snapshot code is on the way.
test-serialize/Deserialize: FAIL
test-serialize/DeserializeAndRunScript: FAIL
test-serialize/DeserializeNatives: FAIL
test-serialize/DeserializeExtensions: FAIL
test-serialize/DeserializeAndRunScript: FAIL || CRASH
test-serialize/DeserializeNatives: FAIL || CRASH
test-serialize/DeserializeExtensions: FAIL || CRASH
# These tests always fail. They are here to test test.py. If
# they don't fail then test.py has failed.
......
......@@ -301,7 +301,7 @@ def JS2C(source, target, env):
else:
ids.append((id, len(lines)))
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
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