Revision: 22286
Author: [email protected]
Date: Wed Jul 9 00:05:10 2014 UTC
Log: Version 3.28.18 (based on bleeding_edge revision r22279)
Reland "Postpone termination exceptions in debug scope." (issue 3408).
Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=22286
Modified:
/trunk/ChangeLog
/trunk/src/assembler.h
/trunk/src/compiler.cc
/trunk/src/debug.cc
/trunk/src/debug.h
/trunk/src/flag-definitions.h
/trunk/src/frames.cc
/trunk/src/frames.h
/trunk/src/full-codegen.cc
/trunk/src/heap.cc
/trunk/src/heap.h
/trunk/src/ic.cc
/trunk/src/ic.h
/trunk/src/mark-compact.cc
/trunk/src/mksnapshot.cc
/trunk/src/objects-inl.h
/trunk/src/objects.h
/trunk/src/parser.cc
/trunk/src/parser.h
/trunk/src/serialize.cc
/trunk/src/serialize.h
/trunk/src/snapshot-source-sink.cc
/trunk/src/snapshot-source-sink.h
/trunk/src/spaces.cc
/trunk/src/store-buffer.cc
/trunk/src/store-buffer.h
/trunk/src/version.cc
/trunk/src/version.h
/trunk/test/cctest/cctest.status
/trunk/test/cctest/test-compiler.cc
/trunk/test/cctest/test-debug.cc
=======================================
--- /trunk/ChangeLog Tue Jul 8 06:57:45 2014 UTC
+++ /trunk/ChangeLog Wed Jul 9 00:05:10 2014 UTC
@@ -1,3 +1,10 @@
+2014-07-09: Version 3.28.18
+
+ Reland "Postpone termination exceptions in debug scope." (issue
3408).
+
+ Performance and stability improvements on all platforms.
+
+
2014-07-08: Version 3.28.17
MIPS: Fix computed properties on object literals with a double as
=======================================
--- /trunk/src/assembler.h Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/assembler.h Wed Jul 9 00:05:10 2014 UTC
@@ -66,6 +66,7 @@
void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
bool serializer_enabled() const { return serializer_enabled_; }
+ void enable_serializer() { serializer_enabled_ = true; }
bool predictable_code_size() const { return predictable_code_size_; }
void set_predictable_code_size(bool value) { predictable_code_size_ =
value; }
=======================================
--- /trunk/src/compiler.cc Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/src/compiler.cc Wed Jul 9 00:05:10 2014 UTC
@@ -933,9 +933,11 @@
cached_data = NULL;
} else if (cached_data_mode == PRODUCE_CACHED_DATA) {
ASSERT(cached_data && !*cached_data);
+ ASSERT(extension == NULL);
} else {
ASSERT(cached_data_mode == CONSUME_CACHED_DATA);
ASSERT(cached_data && *cached_data);
+ ASSERT(extension == NULL);
}
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
@@ -951,6 +953,11 @@
maybe_result = compilation_cache->LookupScript(
source, script_name, line_offset, column_offset,
is_shared_cross_origin, context);
+ if (maybe_result.is_null() && FLAG_serialize_toplevel &&
+ cached_data_mode == CONSUME_CACHED_DATA) {
+ Object* des = CodeSerializer::Deserialize(isolate, *cached_data);
+ return handle(SharedFunctionInfo::cast(des), isolate);
+ }
}
if (!maybe_result.ToHandle(&result)) {
@@ -971,17 +978,21 @@
// Compile the function and add it to the cache.
CompilationInfoWithZone info(script);
info.MarkAsGlobal();
+ info.SetCachedData(cached_data, cached_data_mode);
info.SetExtension(extension);
- info.SetCachedData(cached_data, cached_data_mode);
info.SetContext(context);
if (FLAG_use_strict) info.SetStrictMode(STRICT);
+
result = CompileToplevel(&info);
if (extension == NULL && !result.is_null() && !result->dont_cache()) {
compilation_cache->PutScript(source, context, result);
+ if (FLAG_serialize_toplevel && cached_data_mode ==
PRODUCE_CACHED_DATA) {
+ *cached_data = CodeSerializer::Serialize(result);
+ }
}
if (result.is_null()) isolate->ReportPendingMessages();
} else if (result->ic_age() != isolate->heap()->global_ic_age()) {
- result->ResetForNewContext(isolate->heap()->global_ic_age());
+ result->ResetForNewContext(isolate->heap()->global_ic_age());
}
return result;
}
=======================================
--- /trunk/src/debug.cc Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/debug.cc Wed Jul 9 00:05:10 2014 UTC
@@ -3104,9 +3104,12 @@
}
-DebugScope::DebugScope(Debug* debug) : debug_(debug),
- prev_(debug->debugger_entry()),
- save_(debug_->isolate_) {
+DebugScope::DebugScope(Debug* debug)
+ : debug_(debug),
+ prev_(debug->debugger_entry()),
+ save_(debug_->isolate_),
+ no_termination_exceptons_(debug_->isolate_,
+ StackGuard::TERMINATE_EXECUTION) {
// Link recursive debugger entry.
debug_->thread_local_.current_debug_scope_ = this;
=======================================
--- /trunk/src/debug.h Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/debug.h Wed Jul 9 00:05:10 2014 UTC
@@ -705,6 +705,7 @@
int break_id_; // Previous break id.
bool failed_; // Did the debug context fail to load?
SaveContext save_; // Saves previous context.
+ PostponeInterruptsScope no_termination_exceptons_;
};
=======================================
--- /trunk/src/flag-definitions.h Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/flag-definitions.h Wed Jul 9 00:05:10 2014 UTC
@@ -423,6 +423,8 @@
DEFINE_BOOL(trace_stub_failures, false,
"trace deoptimization of generated code stubs")
+DEFINE_BOOL(serialize_toplevel, false, "enable caching of toplevel
scripts")
+
// compiler.cc
DEFINE_INT(min_preparse_length, 1024,
"minimum length for automatic enable preparsing")
@@ -536,6 +538,7 @@
"Use idle notification to reduce memory footprint.")
// ic.cc
DEFINE_BOOL(use_ic, true, "use inline caching")
+DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
// macro-assembler-ia32.cc
DEFINE_BOOL(native_code_counters, false,
@@ -724,9 +727,6 @@
DEFINE_BOOL(print_handles, false, "report handles after GC")
DEFINE_BOOL(print_global_handles, false, "report global handles after GC")
-// ic.cc
-DEFINE_BOOL(trace_ic, false, "trace inline cache state transitions")
-
// interface.cc
DEFINE_BOOL(print_interfaces, false, "print interfaces")
DEFINE_BOOL(print_interface_details, false, "print interface inference
details")
=======================================
--- /trunk/src/frames.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/frames.cc Wed Jul 9 00:05:10 2014 UTC
@@ -777,9 +777,37 @@
}
-void JavaScriptFrame::PrintTop(Isolate* isolate,
- FILE* file,
- bool print_args,
+void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code*
code,
+ Address pc, FILE* file,
+ bool print_line_number) {
+ PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
+ function->PrintName(file);
+ int code_offset = static_cast<int>(pc - code->instruction_start());
+ PrintF(file, "+%d", code_offset);
+ if (print_line_number) {
+ SharedFunctionInfo* shared = function->shared();
+ int source_pos = code->SourcePosition(pc);
+ Object* maybe_script = shared->script();
+ if (maybe_script->IsScript()) {
+ Script* script = Script::cast(maybe_script);
+ int line = script->GetLineNumber(source_pos) + 1;
+ Object* script_name_raw = script->name();
+ if (script_name_raw->IsString()) {
+ String* script_name = String::cast(script->name());
+ SmartArrayPointer<char> c_script_name =
+ script_name->ToCString(DISALLOW_NULLS,
ROBUST_STRING_TRAVERSAL);
+ PrintF(file, " at %s:%d", c_script_name.get(), line);
+ } else {
+ PrintF(file, " at <unknown>:%d", line);
+ }
+ } else {
+ PrintF(file, " at <unknown>:<unknown>");
+ }
+ }
+}
+
+
+void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool
print_args,
bool print_line_number) {
// constructor calls
DisallowHeapAllocation no_allocation;
@@ -788,37 +816,8 @@
if (it.frame()->is_java_script()) {
JavaScriptFrame* frame = it.frame();
if (frame->IsConstructor()) PrintF(file, "new ");
- // function name
- JSFunction* fun = frame->function();
- fun->PrintName();
- Code* js_code = frame->unchecked_code();
- Address pc = frame->pc();
- int code_offset =
- static_cast<int>(pc - js_code->instruction_start());
- PrintF("+%d", code_offset);
- SharedFunctionInfo* shared = fun->shared();
- if (print_line_number) {
- Code* code = Code::cast(isolate->FindCodeObject(pc));
- int source_pos = code->SourcePosition(pc);
- Object* maybe_script = shared->script();
- if (maybe_script->IsScript()) {
- Script* script = Script::cast(maybe_script);
- int line = script->GetLineNumber(source_pos) + 1;
- Object* script_name_raw = script->name();
- if (script_name_raw->IsString()) {
- String* script_name = String::cast(script->name());
- SmartArrayPointer<char> c_script_name =
- script_name->ToCString(DISALLOW_NULLS,
- ROBUST_STRING_TRAVERSAL);
- PrintF(file, " at %s:%d", c_script_name.get(), line);
- } else {
- PrintF(file, " at <unknown>:%d", line);
- }
- } else {
- PrintF(file, " at <unknown>:<unknown>");
- }
- }
-
+ PrintFunctionAndOffset(frame->function(), frame->unchecked_code(),
+ frame->pc(), file, print_line_number);
if (print_args) {
// function arguments
// (we are intentionally only printing the actually
=======================================
--- /trunk/src/frames.h Wed Jun 4 00:06:13 2014 UTC
+++ /trunk/src/frames.h Wed Jul 9 00:05:10 2014 UTC
@@ -614,9 +614,11 @@
return static_cast<JavaScriptFrame*>(frame);
}
- static void PrintTop(Isolate* isolate,
- FILE* file,
- bool print_args,
+ static void PrintFunctionAndOffset(JSFunction* function, Code* code,
+ Address pc, FILE* file,
+ bool print_line_number);
+
+ static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
bool print_line_number);
protected:
=======================================
--- /trunk/src/full-codegen.cc Thu Jun 26 08:57:53 2014 UTC
+++ /trunk/src/full-codegen.cc Wed Jul 9 00:05:10 2014 UTC
@@ -301,6 +301,11 @@
CodeGenerator::MakeCodePrologue(info, "full");
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
+ if (FLAG_serialize_toplevel &&
+ info->cached_data_mode() == PRODUCE_CACHED_DATA &&
info->is_global()) {
+ masm.enable_serializer();
+ }
+
#ifdef ENABLE_GDB_JIT_INTERFACE
masm.positions_recorder()->StartGDBJITLineInfoRecording();
#endif
=======================================
--- /trunk/src/heap.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/heap.cc Wed Jul 9 00:05:10 2014 UTC
@@ -404,7 +404,7 @@
}
-void Heap::GarbageCollectionPrologue() {
+void Heap::GarbageCollectionPrologue(GarbageCollector collector) {
{ AllowHeapAllocation for_the_first_part_of_prologue;
ClearJSFunctionResultCaches();
gc_count_++;
@@ -435,7 +435,7 @@
ReportStatisticsBeforeGC();
#endif // DEBUG
- store_buffer()->GCPrologue();
+ store_buffer()->GCPrologue(collector == MARK_COMPACTOR);
if (isolate()->concurrent_osr_enabled()) {
isolate()->optimizing_compiler_thread()->AgeBufferedOsrJobs();
@@ -833,7 +833,7 @@
{ GCTracer tracer(this, gc_reason, collector_reason);
ASSERT(AllowHeapAllocation::IsAllowed());
DisallowHeapAllocation no_allocation_during_gc;
- GarbageCollectionPrologue();
+ GarbageCollectionPrologue(collector);
// The GC count was incremented in the prologue. Tell the tracer about
// it.
tracer.set_gc_count(gc_count_);
=======================================
--- /trunk/src/heap.h Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/heap.h Wed Jul 9 00:05:10 2014 UTC
@@ -1698,7 +1698,7 @@
// Code that should be run before and after each GC. Includes some
// reporting/verification activities when compiled with DEBUG set.
- void GarbageCollectionPrologue();
+ void GarbageCollectionPrologue(GarbageCollector collector);
void GarbageCollectionEpilogue();
// Pretenuring decisions are made based on feedback collected during new
=======================================
--- /trunk/src/ic.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/ic.cc Wed Jul 9 00:05:10 2014 UTC
@@ -17,7 +17,6 @@
namespace v8 {
namespace internal {
-#ifdef DEBUG
char IC::TransitionMarkFromState(IC::State state) {
switch (state) {
case UNINITIALIZED: return '0';
@@ -48,25 +47,43 @@
}
-void IC::TraceIC(const char* type,
- Handle<Object> name) {
+#ifdef DEBUG
+
+#define TRACE_GENERIC_IC(isolate, type, reason) \
+ do { \
+ if (FLAG_trace_ic) { \
+ PrintF("[%s patching generic stub in ", type); \
+ JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
+ PrintF(" (%s)]\n", reason); \
+ } \
+ } while (false)
+
+#else
+
+#define TRACE_GENERIC_IC(isolate, type, reason)
+
+#endif // DEBUG
+
+void IC::TraceIC(const char* type, Handle<Object> name) {
if (FLAG_trace_ic) {
Code* new_target = raw_target();
State new_state = new_target->ic_state();
PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
- StackFrameIterator it(isolate());
- while (it.frame()->fp() != this->fp()) it.Advance();
- StackFrame* raw_frame = it.frame();
- if (raw_frame->is_internal()) {
- Code* apply_builtin = isolate()->builtins()->builtin(
- Builtins::kFunctionApply);
- if (raw_frame->unchecked_code() == apply_builtin) {
- PrintF("apply from ");
- it.Advance();
- raw_frame = it.frame();
- }
+
+ // TODO(jkummerow): Add support for "apply". The logic is roughly:
+ // marker = [fp_ + kMarkerOffset];
+ // if marker is smi and marker.value == INTERNAL and
+ // the frame's code == builtin(Builtins::kFunctionApply):
+ // then print "apply from" and advance one frame
+
+ Object* maybe_function =
+ Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
+ if (maybe_function->IsJSFunction()) {
+ JSFunction* function = JSFunction::cast(maybe_function);
+ JavaScriptFrame::PrintFunctionAndOffset(function, function->code(),
pc(),
+ stdout, true);
}
- JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
+
ExtraICState extra_state = new_target->extra_ic_state();
const char* modifier = "";
if (new_target->kind() == Code::KEYED_STORE_IC) {
@@ -77,27 +94,18 @@
TransitionMarkFromState(state()),
TransitionMarkFromState(new_state),
modifier);
+#ifdef OBJECT_PRINT
OFStream os(stdout);
name->Print(os);
+#else
+ name->ShortPrint(stdout);
+#endif
PrintF("]\n");
}
}
-#define TRACE_GENERIC_IC(isolate, type, reason) \
- do { \
- if (FLAG_trace_ic) { \
- PrintF("[%s patching generic stub in ", type); \
- JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
- PrintF(" (%s)]\n", reason); \
- } \
- } while (false)
+#define TRACE_IC(type, name) TraceIC(type, name)
-#else
-#define TRACE_GENERIC_IC(isolate, type, reason)
-#endif // DEBUG
-
-#define TRACE_IC(type, name) \
- ASSERT((TraceIC(type, name), true))
IC::IC(FrameDepth depth, Isolate* isolate)
: isolate_(isolate),
@@ -599,9 +607,11 @@
} else if (state() == PREMONOMORPHIC) {
FunctionPrototypeStub function_prototype_stub(isolate(), kind());
stub = function_prototype_stub.GetCode();
- } else if (state() != MEGAMORPHIC) {
+ } else if (!FLAG_compiled_keyed_generic_loads && state() !=
MEGAMORPHIC) {
ASSERT(state() != GENERIC);
stub = megamorphic_stub();
+ } else if (FLAG_compiled_keyed_generic_loads && state() != GENERIC) {
+ stub = generic_stub();
}
if (!stub.is_null()) {
set_target(*stub);
@@ -616,7 +626,11 @@
uint32_t index;
if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
// Rewrite to the generic keyed load stub.
- if (FLAG_use_ic) set_target(*generic_stub());
+ if (FLAG_use_ic) {
+ set_target(*generic_stub());
+ TRACE_IC("LoadIC", name);
+ TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
+ }
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate(),
@@ -822,6 +836,10 @@
if (UpdatePolymorphicIC(type, name, code)) break;
CopyICToMegamorphicCache(name);
}
+ if (FLAG_compiled_keyed_generic_loads && (kind() == Code::LOAD_IC)) {
+ set_target(*generic_stub());
+ break;
+ }
set_target(*megamorphic_stub());
// Fall through.
case MEGAMORPHIC:
@@ -851,6 +869,11 @@
Handle<Code> LoadIC::megamorphic_stub() {
return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC,
extra_ic_state());
}
+
+
+Handle<Code> LoadIC::generic_stub() const {
+ return KeyedLoadGenericElementStub(isolate()).GetCode();
+}
Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
=======================================
--- /trunk/src/ic.h Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/ic.h Wed Jul 9 00:05:10 2014 UTC
@@ -170,11 +170,8 @@
bool is_target_set() { return target_set_; }
-#ifdef DEBUG
char TransitionMarkFromState(IC::State state);
-
void TraceIC(const char* type, Handle<Object> name);
-#endif
MaybeHandle<Object> TypeError(const char* type,
Handle<Object> object,
@@ -467,6 +464,7 @@
}
virtual Handle<Code> megamorphic_stub();
+ virtual Handle<Code> generic_stub() const;
// Update the inline cache and the global stub cache based on the
// lookup result.
=======================================
--- /trunk/src/mark-compact.cc Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/mark-compact.cc Wed Jul 9 00:05:10 2014 UTC
@@ -4146,12 +4146,23 @@
pages_swept++;
parallel_sweeping_active = true;
} else {
- if (FLAG_gc_verbose) {
- PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in
parallel.\n",
- reinterpret_cast<intptr_t>(p));
+ if (p->scan_on_scavenge()) {
+ SweepPrecisely<SWEEP_ONLY, IGNORE_SKIP_LIST,
IGNORE_FREE_SPACE>(
+ space, p, NULL);
+ pages_swept++;
+ if (FLAG_gc_verbose) {
+ PrintF("Sweeping 0x%" V8PRIxPTR
+ " scan on scavenge page precisely.\n",
+ reinterpret_cast<intptr_t>(p));
+ }
+ } else {
+ if (FLAG_gc_verbose) {
+ PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in
parallel.\n",
+ reinterpret_cast<intptr_t>(p));
+ }
+
p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
+ space->IncreaseUnsweptFreeBytes(p);
}
- p->set_parallel_sweeping(MemoryChunk::PARALLEL_SWEEPING_PENDING);
- space->IncreaseUnsweptFreeBytes(p);
}
space->set_end_of_unswept_pages(p);
break;
=======================================
--- /trunk/src/mksnapshot.cc Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/mksnapshot.cc Wed Jul 9 00:05:10 2014 UTC
@@ -32,17 +32,6 @@
};
-class ListSnapshotSink : public i::SnapshotByteSink {
- public:
- explicit ListSnapshotSink(i::List<char>* data) : data_(data) { }
- virtual ~ListSnapshotSink() {}
- virtual void Put(int byte, const char* description) { data_->Add(byte); }
- virtual int Position() { return data_->length(); }
- private:
- i::List<char>* data_;
-};
-
-
class SnapshotWriter {
public:
explicit SnapshotWriter(const char* snapshot_file)
@@ -93,7 +82,7 @@
return;
i::List<char> startup_blob;
- ListSnapshotSink sink(&startup_blob);
+ i::ListSnapshotSink sink(&startup_blob);
int spaces[] = {
i::NEW_SPACE, i::OLD_POINTER_SPACE, i::OLD_DATA_SPACE,
i::CODE_SPACE,
@@ -417,12 +406,12 @@
// This results in a somewhat smaller snapshot, probably because it
gets
// rid of some things that are cached between garbage collections.
i::List<char> snapshot_data;
- ListSnapshotSink snapshot_sink(&snapshot_data);
+ i::ListSnapshotSink snapshot_sink(&snapshot_data);
i::StartupSerializer ser(internal_isolate, &snapshot_sink);
ser.SerializeStrongReferences();
i::List<char> context_data;
- ListSnapshotSink contex_sink(&context_data);
+ i::ListSnapshotSink contex_sink(&context_data);
i::PartialSerializer context_ser(internal_isolate, &ser, &contex_sink);
context_ser.Serialize(&raw_context);
ser.SerializeWeakReferences();
=======================================
--- /trunk/src/objects-inl.h Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/objects-inl.h Wed Jul 9 00:05:10 2014 UTC
@@ -1478,6 +1478,22 @@
int HeapObject::Size() {
return SizeFromMap(map());
}
+
+
+bool HeapObject::ContainsPointers() {
+ InstanceType type = map()->instance_type();
+ if (type <= LAST_NAME_TYPE) {
+ if (type == SYMBOL_TYPE) {
+ return true;
+ }
+ ASSERT(type < FIRST_NONSTRING_TYPE);
+ // There are four string representations: sequential strings, external
+ // strings, cons strings, and sliced strings.
+ // Only the latter two contain non-map-word pointers to heap objects.
+ return ((type & kIsIndirectStringMask) == kIsIndirectStringTag);
+ }
+ return (type > LAST_DATA_TYPE);
+}
void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
=======================================
--- /trunk/src/objects.h Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/objects.h Wed Jul 9 00:05:10 2014 UTC
@@ -714,6 +714,7 @@
FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE
FIXED_DOUBLE_ARRAY_TYPE,
+ CONSTANT_POOL_ARRAY_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
// Structs.
@@ -740,7 +741,6 @@
BREAK_POINT_INFO_TYPE,
FIXED_ARRAY_TYPE,
- CONSTANT_POOL_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds
to
@@ -1557,15 +1557,15 @@
// Prints this object without details to a message accumulator.
void ShortPrint(StringStream* accumulator);
- // For our gdb macros, we should perhaps change these in the future.
- void Print();
-
DECLARE_CAST(Object)
// Layout description.
static const int kHeaderSize = 0; // Object does not take up any space.
#ifdef OBJECT_PRINT
+ // For our gdb macros, we should perhaps change these in the future.
+ void Print();
+
// Prints this object with details.
void Print(OStream& os); // NOLINT
#endif
@@ -1716,6 +1716,10 @@
// Returns the heap object's size in bytes
inline int Size();
+ // Returns true if this heap object contains only references to other
+ // heap objects.
+ inline bool ContainsPointers();
+
// Given a heap object's map pointer, returns the heap size in bytes
// Useful when the map pointer field is used for other purposes.
// GC internal.
=======================================
--- /trunk/src/parser.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/parser.cc Wed Jul 9 00:05:10 2014 UTC
@@ -182,7 +182,7 @@
}
-ScriptData* ScriptData::New(const char* data, int length) {
+ScriptData* ScriptData::New(const char* data, int length, bool owns_store)
{
// The length is obviously invalid.
if (length % sizeof(unsigned) != 0) {
return NULL;
@@ -190,7 +190,8 @@
int deserialized_data_length = length / sizeof(unsigned);
unsigned* deserialized_data;
- bool owns_store = reinterpret_cast<intptr_t>(data) % sizeof(unsigned) !=
0;
+ owns_store =
+ owns_store || reinterpret_cast<intptr_t>(data) % sizeof(unsigned) !=
0;
if (owns_store) {
// Copy the data to align it.
deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
=======================================
--- /trunk/src/parser.h Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/parser.h Wed Jul 9 00:05:10 2014 UTC
@@ -72,7 +72,7 @@
// The created ScriptData won't take ownership of the data. If the
alignment
// is not correct, this will copy the data (and the created ScriptData
will
// take ownership of the copy).
- static ScriptData* New(const char* data, int length);
+ static ScriptData* New(const char* data, int length, bool owns_store =
false);
virtual ~ScriptData();
virtual int Length();
=======================================
--- /trunk/src/serialize.cc Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/src/serialize.cc Wed Jul 9 00:05:10 2014 UTC
@@ -19,6 +19,7 @@
#include "src/snapshot-source-sink.h"
#include "src/stub-cache.h"
#include "src/v8threads.h"
+#include "src/version.h"
namespace v8 {
namespace internal {
@@ -1794,14 +1795,15 @@
return Page::kPageSize - Page::kObjectStartOffset;
}
}
+
+
+void Serializer::PadByte() { sink_->Put(kNop, "Padding"); }
void Serializer::Pad() {
// The non-branching GetInt will read up to 3 bytes too far, so we need
// to pad the snapshot to make sure we don't read over the end.
- for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
- sink_->Put(kNop, "Padding");
- }
+ for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) PadByte();
}
@@ -1811,4 +1813,101 @@
}
+ScriptData* CodeSerializer::Serialize(Handle<SharedFunctionInfo> info) {
+ // Serialize code object.
+ List<char> payload;
+ ListSnapshotSink listsink(&payload);
+ CodeSerializer ser(info->GetIsolate(), &listsink);
+ DisallowHeapAllocation no_gc;
+ Object** location = Handle<Object>::cast(info).location();
+ ser.VisitPointer(location);
+ ser.Pad();
+
+ // Allocate storage. The payload length may not be aligned. Round up.
+ // TODO(yangguo) replace ScriptData with a more generic super class.
+ int payload_length = payload.length();
+ int raw_length = payload_length / sizeof(unsigned) + kHeaderSize;
+ if (!IsAligned(payload_length, sizeof(unsigned))) raw_length++;
+ unsigned* raw_data = i::NewArray<unsigned>(raw_length);
+ char* payload_data = reinterpret_cast<char*>(raw_data + kHeaderSize);
+
+ // Write header.
+ raw_data[kVersionHashOffset] = Version::Hash();
+ raw_data[kPayloadLengthOffset] = payload_length;
+ STATIC_ASSERT(NEW_SPACE == 0);
+ for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+ raw_data[kReservationsOffset + i] = ser.CurrentAllocationAddress(i);
+ }
+
+ CopyBytes(payload_data, payload.begin(),
static_cast<size_t>(payload_length));
+
+ return new ScriptData(Vector<unsigned>(raw_data, raw_length), true);
+}
+
+
+void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
+ WhereToPoint where_to_point, int
skip) {
+ CHECK(o->IsHeapObject());
+ HeapObject* heap_object = HeapObject::cast(o);
+
+ // The code-caches link to context-specific code objects, which
+ // the startup and context serializes cannot currently handle.
+ ASSERT(!heap_object->IsMap() ||
+ Map::cast(heap_object)->code_cache() ==
+ heap_object->GetHeap()->empty_fixed_array());
+
+ int root_index;
+ if ((root_index = RootIndex(heap_object, how_to_code)) !=
kInvalidRootIndex) {
+ PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
+ return;
+ }
+
+ // TODO(yangguo) wire up builtins.
+ // TODO(yangguo) wire up stubs from stub cache.
+ // TODO(yangguo) wire up script source.
+ // TODO(yangguo) wire up internalized strings
+ ASSERT(!heap_object->IsInternalizedString());
+ // TODO(yangguo) We cannot deal with different hash seeds yet.
+ ASSERT(!heap_object->IsHashTable());
+
+ if (address_mapper_.IsMapped(heap_object)) {
+ int space = SpaceOfObject(heap_object);
+ int address = address_mapper_.MappedTo(heap_object);
+ SerializeReferenceToPreviousObject(space, address, how_to_code,
+ where_to_point, skip);
+ return;
+ }
+
+ if (skip != 0) {
+ sink_->Put(kSkip, "SkipFromSerializeObject");
+ sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
+ }
+ // Object has not yet been serialized. Serialize it here.
+ ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
+ where_to_point);
+ serializer.Serialize();
+}
+
+
+Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
+ const unsigned* raw_data = reinterpret_cast<const
unsigned*>(data->Data());
+ CHECK_EQ(Version::Hash(), raw_data[kVersionHashOffset]);
+ int payload_length = raw_data[kPayloadLengthOffset];
+ const byte* payload_data =
+ reinterpret_cast<const byte*>(raw_data + kHeaderSize);
+ ASSERT_LE(payload_length, data->Length() - kHeaderSize);
+
+ SnapshotByteSource payload(payload_data, payload_length);
+ Deserializer deserializer(&payload);
+ STATIC_ASSERT(NEW_SPACE == 0);
+ // TODO(yangguo) what happens if remaining new space is too small?
+ for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
+ deserializer.set_reservation(
+ i, raw_data[CodeSerializer::kReservationsOffset + i]);
+ }
+ Object* root;
+ deserializer.DeserializePartial(isolate, &root);
+ ASSERT(root->IsSharedFunctionInfo());
+ return root;
+}
} } // namespace v8::internal
=======================================
--- /trunk/src/serialize.h Tue Jun 24 00:06:56 2014 UTC
+++ /trunk/src/serialize.h Wed Jul 9 00:05:10 2014 UTC
@@ -8,6 +8,7 @@
#include "src/hashmap.h"
#include "src/heap-profiler.h"
#include "src/isolate.h"
+#include "src/parser.h"
#include "src/snapshot-source-sink.h"
namespace v8 {
@@ -469,6 +470,7 @@
SerializationAddressMapper address_mapper_;
intptr_t root_index_wave_front_;
void Pad();
+ void PadByte();
friend class ObjectSerializer;
friend class Deserializer;
@@ -551,6 +553,29 @@
};
+class CodeSerializer : public Serializer {
+ public:
+ CodeSerializer(Isolate* isolate, SnapshotByteSink* sink)
+ : Serializer(isolate, sink) {
+ set_root_index_wave_front(Heap::kStrongRootListLength);
+ InitializeCodeAddressMap();
+ }
+
+ static ScriptData* Serialize(Handle<SharedFunctionInfo> info);
+ virtual void SerializeObject(Object* o, HowToCode how_to_code,
+ WhereToPoint where_to_point, int skip);
+
+ static Object* Deserialize(Isolate* isolate, ScriptData* data);
+
+ // The data header consists of int-sized entries:
+ // [0] version hash
+ // [1] length in bytes
+ // [2..8] reservation sizes for spaces from NEW_SPACE to
PROPERTY_CELL_SPACE.
+ static const int kHeaderSize = 9;
+ static const int kVersionHashOffset = 0;
+ static const int kPayloadLengthOffset = 1;
+ static const int kReservationsOffset = 2;
+};
} } // namespace v8::internal
#endif // V8_SERIALIZE_H_
=======================================
--- /trunk/src/snapshot-source-sink.cc Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/src/snapshot-source-sink.cc Wed Jul 9 00:05:10 2014 UTC
@@ -90,6 +90,12 @@
return false;
}
}
+
+
+void DebugSnapshotSink::Put(int byte, const char* description) {
+ PrintF("%24s: %x\n", description, byte);
+ sink_->Put(byte, description);
+}
} // namespace v8::internal
} // namespace v8
=======================================
--- /trunk/src/snapshot-source-sink.h Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/src/snapshot-source-sink.h Wed Jul 9 00:05:10 2014 UTC
@@ -82,6 +82,42 @@
};
+class DummySnapshotSink : public SnapshotByteSink {
+ public:
+ DummySnapshotSink() : length_(0) {}
+ virtual ~DummySnapshotSink() {}
+ virtual void Put(int byte, const char* description) { length_++; }
+ virtual int Position() { return length_; }
+
+ private:
+ int length_;
+};
+
+
+// Wrap a SnapshotByteSink into a DebugSnapshotSink to get debugging
output.
+class DebugSnapshotSink : public SnapshotByteSink {
+ public:
+ explicit DebugSnapshotSink(SnapshotByteSink* chained) : sink_(chained) {}
+ virtual void Put(int byte, const char* description) V8_OVERRIDE;
+ virtual int Position() V8_OVERRIDE { return sink_->Position(); }
+
+ private:
+ SnapshotByteSink* sink_;
+};
+
+
+class ListSnapshotSink : public i::SnapshotByteSink {
+ public:
+ explicit ListSnapshotSink(i::List<char>* data) : data_(data) {}
+ virtual void Put(int byte, const char* description) V8_OVERRIDE {
+ data_->Add(byte);
+ }
+ virtual int Position() V8_OVERRIDE { return data_->length(); }
+
+ private:
+ i::List<char>* data_;
+};
+
} // namespace v8::internal
} // namespace v8
=======================================
--- /trunk/src/spaces.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/spaces.cc Wed Jul 9 00:05:10 2014 UTC
@@ -18,6 +18,9 @@
// HeapObjectIterator
HeapObjectIterator::HeapObjectIterator(PagedSpace* space) {
+ // Check that we actually can iterate this space.
+ ASSERT(space->is_iterable());
+
// You can't actually iterate over the anchor page. It is not a real
page,
// just an anchor for the double linked page list. Initialize as if we
have
// reached the end of the anchor page, then the first iteration will
move on
@@ -32,6 +35,9 @@
HeapObjectIterator::HeapObjectIterator(PagedSpace* space,
HeapObjectCallback size_func) {
+ // Check that we actually can iterate this space.
+ ASSERT(space->is_iterable());
+
// You can't actually iterate over the anchor page. It is not a real
page,
// just an anchor for the double linked page list. Initialize the
current
// address and end as NULL, then the first iteration will move on
@@ -66,9 +72,6 @@
Address cur, Address end,
HeapObjectIterator::PageMode mode,
HeapObjectCallback size_f) {
- // Check that we actually can iterate this space.
- ASSERT(space->is_iterable());
-
space_ = space;
cur_addr_ = cur;
cur_end_ = end;
=======================================
--- /trunk/src/store-buffer.cc Tue Jul 8 00:05:42 2014 UTC
+++ /trunk/src/store-buffer.cc Wed Jul 9 00:05:10 2014 UTC
@@ -11,6 +11,7 @@
#include "src/base/atomicops.h"
#include "src/counters.h"
#include "src/store-buffer-inl.h"
+#include "src/utils.h"
namespace v8 {
namespace internal {
@@ -22,10 +23,13 @@
old_start_(NULL),
old_limit_(NULL),
old_top_(NULL),
+ old_regular_limit_(NULL),
old_reserved_limit_(NULL),
+ old_virtual_memory_(NULL),
+ old_store_buffer_length_(0),
old_buffer_is_sorted_(false),
old_buffer_is_filtered_(false),
- during_gc_(false),
+ allow_overflow_(false),
store_buffer_rebuilding_enabled_(false),
callback_(NULL),
may_move_store_buffer_entries_(true),
@@ -44,8 +48,16 @@
reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize *
2));
limit_ = start_ + (kStoreBufferSize / kPointerSize);
+ // We set the maximum store buffer size to the maximum size of a
semi-space.
+ // The store buffer may reach this limit during a full garbage
collection.
+ // Note that half of the semi-space should be good enough since half of
the
+ // memory in the semi-space are not object pointers.
+ old_store_buffer_length_ =
+ Max(static_cast<int>(heap_->MaxSemiSpaceSize() / sizeof(Address)),
+ kOldRegularStoreBufferLength);
+
old_virtual_memory_ =
- new base::VirtualMemory(kOldStoreBufferLength * kPointerSize);
+ new base::VirtualMemory(old_store_buffer_length_ * kPointerSize);
old_top_ = old_start_ =
reinterpret_cast<Address*>(old_virtual_memory_->address());
// Don't know the alignment requirements of the OS, but it is certainly
not
@@ -54,9 +66,12 @@
int initial_length =
static_cast<int>(base::OS::CommitPageSize() / kPointerSize);
ASSERT(initial_length > 0);
- ASSERT(initial_length <= kOldStoreBufferLength);
+ ASSERT(initial_length <= kOldRegularStoreBufferLength);
+ ASSERT(initial_length <= old_store_buffer_length_);
+ ASSERT(kOldRegularStoreBufferLength <= old_store_buffer_length_);
old_limit_ = old_start_ + initial_length;
- old_reserved_limit_ = old_start_ + kOldStoreBufferLength;
+ old_regular_limit_ = old_start_ + kOldRegularStoreBufferLength;
+ old_reserved_limit_ = old_start_ + old_store_buffer_length_;
CHECK(old_virtual_memory_->Commit(
reinterpret_cast<void*>(old_start_),
@@ -93,8 +108,13 @@
delete old_virtual_memory_;
delete[] hash_set_1_;
delete[] hash_set_2_;
- old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
- start_ = limit_ = NULL;
+ old_start_ = NULL;
+ old_top_ = NULL;
+ old_limit_ = NULL;
+ old_reserved_limit_ = NULL;
+ old_regular_limit_ = NULL;
+ start_ = NULL;
+ limit_ = NULL;
heap_->public_set_store_buffer_top(start_);
}
@@ -126,11 +146,37 @@
bool StoreBuffer::SpaceAvailable(intptr_t space_needed) {
return old_limit_ - old_top_ >= space_needed;
}
+
+
+template<StoreBuffer::ExemptPopularPagesMode mode>
+void StoreBuffer::IterativelyExemptPopularPages(intptr_t space_needed) {
+ // Sample 1 entry in 97 and filter out the pages where we estimate that
more
+ // than 1 in 8 pointers are to new space.
+ static const int kSampleFinenesses = 5;
+ static const struct Samples {
+ int prime_sample_step;
+ int threshold;
+ } samples[kSampleFinenesses] = {
+ { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
+ { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
+ { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
+ { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
+ { 1, 0}
+ };
+ for (int i = 0; i < kSampleFinenesses; i++) {
+ ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
+ // As a last resort we mark all pages as being exempt from the store
buffer.
+ ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
+ if (mode == ENSURE_SPACE && SpaceAvailable(space_needed)) return;
+ else if (mode == SHRINK_TO_REGULAR_SIZE && old_top_ < old_limit_)
return;
+ }
+}
void StoreBuffer::EnsureSpace(intptr_t space_needed) {
while (old_limit_ - old_top_ < space_needed &&
- old_limit_ < old_reserved_limit_) {
+ ((!allow_overflow_ && old_limit_ < old_regular_limit_) ||
+ (allow_overflow_ && old_limit_ < old_reserved_limit_))) {
size_t grow = old_limit_ - old_start_; // Double size.
CHECK(old_virtual_memory_->Commit(reinterpret_cast<void*>(old_limit_),
grow * kPointerSize,
@@ -162,26 +208,8 @@
if (SpaceAvailable(space_needed)) return;
- // Sample 1 entry in 97 and filter out the pages where we estimate that
more
- // than 1 in 8 pointers are to new space.
- static const int kSampleFinenesses = 5;
- static const struct Samples {
- int prime_sample_step;
- int threshold;
- } samples[kSampleFinenesses] = {
- { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
- { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
- { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
- { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
- { 1, 0}
- };
- for (int i = 0; i < kSampleFinenesses; i++) {
- ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
- // As a last resort we mark all pages as being exempt from the store
buffer.
- ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
- if (SpaceAvailable(space_needed)) return;
- }
- UNREACHABLE();
+ IterativelyExemptPopularPages<ENSURE_SPACE>(space_needed);
+ ASSERT(SpaceAvailable(space_needed));
}
@@ -328,9 +356,9 @@
}
-void StoreBuffer::GCPrologue() {
+void StoreBuffer::GCPrologue(bool allow_overflow) {
ClearFilteringHashSets();
- during_gc_ = true;
+ allow_overflow_ = allow_overflow;
}
@@ -366,7 +394,13 @@
void StoreBuffer::GCEpilogue() {
- during_gc_ = false;
+ if (allow_overflow_ && old_limit_ > old_regular_limit_) {
+ IterativelyExemptPopularPages<SHRINK_TO_REGULAR_SIZE>(0);
+ ASSERT(old_limit_ < old_regular_limit_);
+ old_virtual_memory_->Uncommit(old_limit_, old_regular_limit_ -
old_limit_);
+ }
+
+ allow_overflow_ = false;
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
Verify();
@@ -488,25 +522,22 @@
FindPointersToNewSpaceInRegion(start, end, slot_callback,
clear_maps);
} else {
Page* page = reinterpret_cast<Page*>(chunk);
- PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
- Address start = page->area_start();
- Address end = page->area_end();
- if (owner == heap_->map_space()) {
- ASSERT(page->WasSweptPrecisely());
- HeapObjectIterator iterator(page, NULL);
- for (HeapObject* heap_object = iterator.Next(); heap_object !=
NULL;
- heap_object = iterator.Next()) {
- // We skip free space objects.
- if (!heap_object->IsFiller()) {
- FindPointersToNewSpaceInRegion(
- heap_object->address() + HeapObject::kHeaderSize,
- heap_object->address() + heap_object->Size(),
slot_callback,
- clear_maps);
- }
+ ASSERT(page->owner() == heap_->map_space() ||
+ page->owner() == heap_->old_pointer_space());
+ CHECK(!page->WasSweptConservatively());
+
+ HeapObjectIterator iterator(page, NULL);
+ for (HeapObject* heap_object = iterator.Next();
+ heap_object != NULL;
+ heap_object = iterator.Next()) {
+ // We iterate over objects that contain pointers only.
+ if (heap_object->ContainsPointers()) {
+ FindPointersToNewSpaceInRegion(
+ heap_object->address() + HeapObject::kHeaderSize,
+ heap_object->address() + heap_object->Size(),
+ slot_callback,
+ clear_maps);
}
- } else {
- FindPointersToNewSpaceInRegion(
- start, end, slot_callback, clear_maps);
}
}
}
=======================================
--- /trunk/src/store-buffer.h Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/src/store-buffer.h Wed Jul 9 00:05:10 2014 UTC
@@ -19,11 +19,6 @@
typedef void (*ObjectSlotCallback)(HeapObject** from, HeapObject* to);
-typedef void (StoreBuffer::*RegionCallback)(Address start,
- Address end,
- ObjectSlotCallback
slot_callback,
- bool clear_maps);
-
// Used to implement the write barrier by collecting addresses of pointers
// between spaces.
class StoreBuffer {
@@ -68,13 +63,13 @@
static const int kStoreBufferOverflowBit = 1 << (14 + kPointerSizeLog2);
static const int kStoreBufferSize = kStoreBufferOverflowBit;
static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address);
- static const int kOldStoreBufferLength = kStoreBufferLength * 16;
+ static const int kOldRegularStoreBufferLength = kStoreBufferLength * 16;
static const int kHashSetLengthLog2 = 12;
static const int kHashSetLength = 1 << kHashSetLengthLog2;
void Compact();
- void GCPrologue();
+ void GCPrologue(bool allow_overflow);
void GCEpilogue();
Object*** Limit() { return reinterpret_cast<Object***>(old_limit_); }
@@ -118,12 +113,27 @@
Address* old_start_;
Address* old_limit_;
Address* old_top_;
+
+ // The regular limit specifies how big the store buffer may become during
+ // mutator execution or while scavenging.
+ Address* old_regular_limit_;
+
+ // The reserved limit is bigger then the regular limit. It should be the
size
+ // of a semi-space to avoid new scan-on-scavenge during new space
evacuation
+ // after sweeping in a full garbage collection.
Address* old_reserved_limit_;
+
base::VirtualMemory* old_virtual_memory_;
+ int old_store_buffer_length_;
bool old_buffer_is_sorted_;
bool old_buffer_is_filtered_;
- bool during_gc_;
+
+ // If allow_overflow_ is set, we allow the store buffer to grow until
+ // old_reserved_limit_. But we will shrink the store buffer in the
epilogue to
+ // stay within the old_regular_limit_.
+ bool allow_overflow_;
+
// The garbage collector iterates over many pointers to new space that
are not
// handled by the store buffer. This flag indicates whether the pointers
// found by the callbacks should be added to the store buffer or not.
@@ -146,6 +156,14 @@
void Uniq();
void ExemptPopularPages(int prime_sample_step, int threshold);
+ enum ExemptPopularPagesMode {
+ ENSURE_SPACE,
+ SHRINK_TO_REGULAR_SIZE
+ };
+
+ template <ExemptPopularPagesMode mode>
+ void IterativelyExemptPopularPages(intptr_t space_needed);
+
// Set the map field of the object to NULL if contains a map.
inline void ClearDeadObject(HeapObject *object);
@@ -156,17 +174,6 @@
ObjectSlotCallback slot_callback,
bool clear_maps);
- // For each region of pointers on a page in use from an old space call
- // visit_pointer_region callback.
- // If either visit_pointer_region or callback can cause an allocation
- // in old space and changes in allocation watermark then
- // can_preallocate_during_iteration should be set to true.
- void IteratePointersOnPage(
- PagedSpace* space,
- Page* page,
- RegionCallback region_callback,
- ObjectSlotCallback slot_callback);
-
void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
bool clear_maps);
=======================================
--- /trunk/src/version.cc Tue Jul 8 06:57:45 2014 UTC
+++ /trunk/src/version.cc Wed Jul 9 00:05:10 2014 UTC
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 28
-#define BUILD_NUMBER 17
+#define BUILD_NUMBER 18
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
=======================================
--- /trunk/src/version.h Tue Apr 29 16:30:47 2014 UTC
+++ /trunk/src/version.h Wed Jul 9 00:05:10 2014 UTC
@@ -16,6 +16,7 @@
static int GetBuild() { return build_; }
static int GetPatch() { return patch_; }
static bool IsCandidate() { return candidate_; }
+ static int Hash() { return (major_ << 20) ^ (minor_ << 10) ^ patch_; }
// Calculate the V8 version string.
static void GetString(Vector<char> str);
=======================================
--- /trunk/test/cctest/cctest.status Tue Jul 1 11:58:10 2014 UTC
+++ /trunk/test/cctest/cctest.status Wed Jul 9 00:05:10 2014 UTC
@@ -75,6 +75,9 @@
# BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup)
'test-cpu-profiler/*': [PASS, FLAKY],
+ # TODO(yangguo): Temporarily disable code serializer test
+ 'test-compiler/SerializeToplevel': [SKIP],
+
############################################################################
# Slow tests.
'test-api/Threading1': [PASS, ['mode == debug', SLOW]],
=======================================
--- /trunk/test/cctest/test-compiler.cc Mon Jun 30 00:04:54 2014 UTC
+++ /trunk/test/cctest/test-compiler.cc Wed Jul 9 00:05:10 2014 UTC
@@ -32,6 +32,7 @@
#include "src/compiler.h"
#include "src/disasm.h"
+#include "src/parser.h"
#include "test/cctest/cctest.h"
using namespace v8::internal;
@@ -396,6 +397,46 @@
CHECK_EQ(fun1->code(), fun2->code());
}
}
+
+
+TEST(SerializeToplevel) {
+ FLAG_serialize_toplevel = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> context = CcTest::NewContext(PRINT_EXTENSION);
+ v8::Context::Scope context_scope(context);
+
+ const char* source1 = "1 + 1";
+ const char* source2 = "1 + 2"; // Use alternate string to verify
caching.
+
+ Isolate* isolate = CcTest::i_isolate();
+ Handle<String> source1_string = isolate->factory()
+
->NewStringFromUtf8(CStrVector(source1))
+ .ToHandleChecked();
+ Handle<String> source2_string = isolate->factory()
+
->NewStringFromUtf8(CStrVector(source2))
+ .ToHandleChecked();
+
+ ScriptData* cache = NULL;
+
+ Handle<SharedFunctionInfo> orig =
+ Compiler::CompileScript(source1_string, Handle<String>(), 0, 0,
false,
+ Handle<Context>(isolate->native_context()),
NULL,
+ &cache, PRODUCE_CACHED_DATA,
NOT_NATIVES_CODE);
+
+ Handle<SharedFunctionInfo> info =
+ Compiler::CompileScript(source2_string, Handle<String>(), 0, 0,
false,
+ Handle<Context>(isolate->native_context()),
NULL,
+ &cache, CONSUME_CACHED_DATA,
NOT_NATIVES_CODE);
+
+ CHECK_NE(*orig, *info);
+ Handle<JSFunction> fun =
+ isolate->factory()->NewFunctionFromSharedFunctionInfo(
+ info, isolate->native_context());
+ Handle<JSObject> global(isolate->context()->global_object());
+ Handle<Object> result =
+ Execution::Call(isolate, fun, global, 0, NULL).ToHandleChecked();
+ CHECK_EQ(2, Handle<Smi>::cast(result)->value());
+}
#ifdef ENABLE_DISASSEMBLER
=======================================
--- /trunk/test/cctest/test-debug.cc Mon Jul 7 00:05:07 2014 UTC
+++ /trunk/test/cctest/test-debug.cc Wed Jul 9 00:05:10 2014 UTC
@@ -7374,9 +7374,6 @@
// Wait for at most 2 seconds for the terminate request.
CHECK(terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
terminate_already_fired = true;
- v8::internal::Isolate* isolate =
-
v8::Utils::OpenHandle(*event_details.GetEventContext())->GetIsolate();
- CHECK(isolate->stack_guard()->CheckTerminateExecution());
}
@@ -7403,6 +7400,8 @@
v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate);
TerminationThread terminator(isolate);
terminator.Start();
+ v8::TryCatch try_catch;
v8::Debug::DebugBreak(isolate);
CompileRun("while (true);");
+ CHECK(try_catch.HasTerminated());
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.