Version 3.19.14
Fixed crashes when calling new Array(a) with a single argument that could result in creating a holey array with a packed elements kind. (Chromium issue 245480)
Fixed issues in parallel compilation. (Chromium issue 248076)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@15100 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 6117e56..907760a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-06-13: Version 3.19.14
+
+ Fixed crashes when calling new Array(a) with a single argument that
+ could result in creating a holey array with a packed elements kind.
+ (Chromium issue 245480)
+
+ Fixed issues in parallel compilation.
+ (Chromium issue 248076)
+
+ Performance and stability improvements on all platforms.
+
+
2013-06-11: Version 3.19.13
Performance and stability improvements on all platforms.
diff --git a/include/v8.h b/include/v8.h
index c0bec79..6fcc332 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5333,7 +5333,7 @@
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 130;
+ static const int kEmptyStringRootIndex = 131;
static const int kNodeClassIdOffset = 1 * kApiPointerSize;
static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5343,10 +5343,10 @@
static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5;
- static const int kJSObjectType = 0xaf;
+ static const int kJSObjectType = 0xb0;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
- static const int kForeignType = 0x87;
+ static const int kForeignType = 0x88;
static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3;
diff --git a/src/api.cc b/src/api.cc
index 20496fe..5491971 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -183,6 +183,10 @@
heap_stats.cell_space_size = &cell_space_size;
intptr_t cell_space_capacity;
heap_stats.cell_space_capacity = &cell_space_capacity;
+ intptr_t property_cell_space_size;
+ heap_stats.property_cell_space_size = &property_cell_space_size;
+ intptr_t property_cell_space_capacity;
+ heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
intptr_t lo_space_size;
heap_stats.lo_space_size = &lo_space_size;
int global_handle_count;
@@ -6162,7 +6166,7 @@
ENTER_V8(isolate);
for (i::Handle<i::Object> array_obj(obj->weak_first_array(), isolate);
- *array_obj != i::Smi::FromInt(0);) {
+ !array_obj->IsUndefined();) {
i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*array_obj));
typed_array->Neuter();
array_obj = i::handle(typed_array->weak_next(), isolate);
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 1e0d5c1..17831c8 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -179,24 +179,22 @@
}
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+ ASSERT(rmode_ == RelocInfo::CELL);
Address address = Memory::Address_at(pc_);
- return Handle<JSGlobalPropertyCell>(
- reinterpret_cast<JSGlobalPropertyCell**>(address));
+ return Handle<Cell>(reinterpret_cast<Cell**>(address));
}
-JSGlobalPropertyCell* RelocInfo::target_cell() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ return Cell::FromValueAddress(Memory::Address_at(pc_));
}
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
- WriteBarrierMode mode) {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
// TODO(1550) We are passing NULL as a slot because cell can never be on
@@ -286,8 +284,8 @@
visitor->VisitEmbeddedPointer(this);
} else if (RelocInfo::IsCodeTarget(mode)) {
visitor->VisitCodeTarget(this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- visitor->VisitGlobalPropertyCell(this);
+ } else if (mode == RelocInfo::CELL) {
+ visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
@@ -314,8 +312,8 @@
StaticVisitor::VisitEmbeddedPointer(heap, this);
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(heap, this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- StaticVisitor::VisitGlobalPropertyCell(heap, this);
+ } else if (mode == RelocInfo::CELL) {
+ StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index b26bf7e..ee6eb97 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -3504,7 +3504,7 @@
// Get the map location in scratch and patch it.
__ GetRelocatedValueLocation(inline_site, scratch);
__ ldr(scratch, MemOperand(scratch));
- __ str(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+ __ str(map, FieldMemOperand(scratch, Cell::kValueOffset));
}
// Register mapping: r3 is object map and r4 is function prototype.
@@ -4637,7 +4637,7 @@
masm->isolate()->heap()->the_hole_value());
// Load the cache state into r3.
- __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
// A monomorphic cache hit or an already megamorphic state: invoke the
// function without changing the state.
@@ -4652,10 +4652,10 @@
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne);
- __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), ne);
+ __ str(ip, FieldMemOperand(r2, Cell::kValueOffset), ne);
// An uninitialized cache is patched with the function.
- __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), eq);
+ __ str(r1, FieldMemOperand(r2, Cell::kValueOffset), eq);
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -4677,7 +4677,7 @@
masm->isolate()->heap()->the_hole_value());
// Load the cache state into r3.
- __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
// A monomorphic cache hit or an already megamorphic state: invoke the
// function without changing the state.
@@ -4711,7 +4711,7 @@
// write-barrier is needed.
__ bind(&megamorphic);
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
__ jmp(&done);
// An uninitialized cache is patched with the function or sentinel to
@@ -4729,11 +4729,11 @@
TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
GetInitialFastElementsKind());
__ mov(r3, Operand(initial_kind_sentinel));
- __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
__ b(&done);
__ bind(¬_array_function);
- __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(r1, FieldMemOperand(r2, Cell::kValueOffset));
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -4809,7 +4809,7 @@
ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
masm->isolate()->heap()->undefined_value());
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(ip, FieldMemOperand(r2, Cell::kValueOffset));
}
// Check for function proxy.
__ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE));
@@ -7332,14 +7332,13 @@
__ CompareObjectType(r3, r3, r4, MAP_TYPE);
__ Assert(eq, "Unexpected initial map for Array function");
- // We should either have undefined in ebx or a valid jsglobalpropertycell
+ // We should either have undefined in ebx or a valid cell
Label okay_here;
- Handle<Map> global_property_cell_map(
- masm->isolate()->heap()->global_property_cell_map());
+ Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
__ cmp(r2, Operand(undefined_sentinel));
__ b(eq, &okay_here);
__ ldr(r3, FieldMemOperand(r2, 0));
- __ cmp(r3, Operand(global_property_cell_map));
+ __ cmp(r3, Operand(cell_map));
__ Assert(eq, "Expected property cell in register ebx");
__ bind(&okay_here);
}
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 8b24bf1..39a4018 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -129,7 +129,7 @@
CompilationInfo* info = info_;
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
- profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+ profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -327,9 +327,9 @@
void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
__ mov(r2, Operand(profiling_counter_));
- __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset));
__ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC);
- __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
}
@@ -345,7 +345,7 @@
}
__ mov(r2, Operand(profiling_counter_));
__ mov(r3, Operand(Smi::FromInt(reset_value)));
- __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
+ __ str(r3, FieldMemOperand(r2, Cell::kValueOffset));
}
@@ -1164,15 +1164,13 @@
Label non_proxy;
__ bind(&fixed_array);
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(
- Handle<Object>(
- Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
- isolate()));
+ Handle<Cell> cell = isolate()->factory()->NewCell(
+ Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+ isolate()));
RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
__ LoadHeapObject(r1, cell);
__ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
- __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset));
+ __ str(r2, FieldMemOperand(r1, Cell::kValueOffset));
__ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
__ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
@@ -1991,8 +1989,12 @@
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::INITIAL:
- case Yield::SUSPEND: {
+ case Yield::SUSPEND:
+ // Pop value from top-of-stack slot; box result into result register.
+ EmitCreateIteratorResult(false);
+ __ push(result_register());
+ // Fall through.
+ case Yield::INITIAL: {
VisitForStackValue(expr->generator_object());
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ ldr(context_register(),
@@ -2001,12 +2003,8 @@
Label resume;
__ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
__ b(ne, &resume);
- if (expr->yield_kind() == Yield::SUSPEND) {
- EmitReturnIteratorResult(false);
- } else {
- __ pop(result_register());
- EmitReturnSequence();
- }
+ __ pop(result_register());
+ EmitReturnSequence();
__ bind(&resume);
context()->Plug(result_register());
@@ -2018,7 +2016,10 @@
__ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
__ str(r1, FieldMemOperand(result_register(),
JSGeneratorObject::kContinuationOffset));
- EmitReturnIteratorResult(true);
+ // Pop value from top-of-stack slot, box result into result register.
+ EmitCreateIteratorResult(true);
+ EmitUnwindBeforeReturn();
+ EmitReturnSequence();
break;
}
@@ -2048,10 +2049,10 @@
// try { received = yield result.value }
__ bind(&l_try);
- __ pop(r0); // result.value
+ EmitCreateIteratorResult(false); // pop and box to r0
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(r0); // result.value
+ __ push(r0); // result
__ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g
__ push(r3); // g
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
@@ -2059,7 +2060,8 @@
MemOperand(fp, StandardFrameConstants::kContextOffset));
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
__ b(ne, &l_resume);
- EmitReturnIteratorResult(false);
+ __ pop(r0); // result
+ EmitReturnSequence();
__ bind(&l_resume); // received in r0
__ PopTryHandler();
@@ -2214,13 +2216,20 @@
}
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Label gc_required;
Label allocated;
Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
+ __ jmp(&allocated);
+
+ __ bind(&gc_required);
+ __ Push(Smi::FromInt(map->instance_size()));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ __ ldr(context_register(),
+ MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ mov(r1, Operand(map));
@@ -2240,26 +2249,6 @@
// root set.
__ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
-
- if (done) {
- // Exit all nested statements.
- NestedStatement* current = nesting_stack_;
- int stack_depth = 0;
- int context_length = 0;
- while (current != NULL) {
- current = current->Exit(&stack_depth, &context_length);
- }
- __ Drop(stack_depth);
- }
-
- EmitReturnSequence();
-
- __ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
- __ ldr(context_register(),
- MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ jmp(&allocated);
}
@@ -2683,8 +2672,7 @@
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
__ mov(r2, Operand(cell));
@@ -2879,8 +2867,7 @@
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
__ mov(r2, Operand(cell));
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index fbb9c6e..1d4ed5f 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -929,7 +929,7 @@
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
- int value_count = hydrogen_env->length();
+ int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
LEnvironment* result = new(zone()) LEnvironment(
hydrogen_env->closure(),
hydrogen_env->frame_type(),
@@ -940,13 +940,15 @@
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- for (int i = 0; i < value_count; ++i) {
+ for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
HValue* value = hydrogen_env->values()->at(i);
LOperand* op = NULL;
if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
@@ -958,6 +960,22 @@
value->CheckFlag(HInstruction::kUint32));
}
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ ASSERT(HInstruction::cast(value)->IsLinked());
+ LOperand* op = UseAny(value);
+ result->AddValue(op,
+ value->representation(),
+ value->CheckFlag(HInstruction::kUint32));
+ }
+ }
+
if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 96befb0..253c63d 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -87,20 +87,7 @@
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
- for (int i = 0 ; i < prototype_maps_.length(); i++) {
- prototype_maps_.at(i)->AddDependentCode(
- DependentCode::kPrototypeCheckGroup, code);
- }
- for (int i = 0 ; i < transition_maps_.length(); i++) {
- transition_maps_.at(i)->AddDependentCode(
- DependentCode::kTransitionGroup, code);
- }
- if (graph()->depends_on_empty_array_proto_elements()) {
- isolate()->initial_object_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- isolate()->initial_array_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- }
+ info()->CommitDependentMaps(code);
}
@@ -593,27 +580,15 @@
void LCodeGen::WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* pushed_arguments_index,
- int* pushed_arguments_count) {
+ Translation* translation) {
if (environment == NULL) return;
// The translation includes one command per value in the environment.
- int translation_size = environment->values()->length();
+ int translation_size = environment->translation_size();
// The output frame height does not include the parameters.
int height = translation_size - environment->parameter_count();
- // Function parameters are arguments to the outermost environment. The
- // arguments index points to the first element of a sequence of tagged
- // values on the stack that represent the arguments. This needs to be
- // kept in sync with the LArgumentsElements implementation.
- *pushed_arguments_index = -environment->parameter_count();
- *pushed_arguments_count = environment->parameter_count();
-
- WriteTranslation(environment->outer(),
- translation,
- pushed_arguments_index,
- pushed_arguments_count);
+ WriteTranslation(environment->outer(), translation);
bool has_closure_id = !info()->closure().is_null() &&
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
@@ -645,23 +620,6 @@
break;
}
- // Inlined frames which push their arguments cause the index to be
- // bumped and another stack area to be used for materialization,
- // otherwise actual argument values are unknown for inlined frames.
- bool arguments_known = true;
- int arguments_index = *pushed_arguments_index;
- int arguments_count = *pushed_arguments_count;
- if (environment->entry() != NULL) {
- arguments_known = environment->entry()->arguments_pushed();
- arguments_index = arguments_index < 0
- ? GetStackSlotCount() : arguments_index + arguments_count;
- arguments_count = environment->entry()->arguments_count() + 1;
- if (environment->entry()->arguments_pushed()) {
- *pushed_arguments_index = arguments_index;
- *pushed_arguments_count = arguments_count;
- }
- }
-
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either
@@ -673,10 +631,7 @@
AddToTranslation(translation,
environment->spilled_registers()[value->index()],
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
} else if (
value->IsDoubleRegister() &&
environment->spilled_double_registers()[value->index()] != NULL) {
@@ -685,20 +640,36 @@
translation,
environment->spilled_double_registers()[value->index()],
false,
- false,
- arguments_known,
- arguments_index,
- arguments_count);
+ false);
}
}
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsRegister() ||
+ environment->spilled_registers()[value->index()] == NULL);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsDoubleRegister() ||
+ environment->spilled_double_registers()[value->index()] == NULL);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
}
}
@@ -706,17 +677,8 @@
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count) {
- if (op == NULL) {
- // TODO(twuerthinger): Introduce marker operands to indicate that this value
- // is not present and must be reconstructed from the deoptimizer. Currently
- // this is only used for the arguments object.
- translation->StoreArgumentsObject(
- arguments_known, arguments_index, arguments_count);
- } else if (op->IsStackSlot()) {
+ bool is_uint32) {
+ if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
} else if (is_uint32) {
@@ -823,8 +785,6 @@
int frame_count = 0;
int jsframe_count = 0;
- int args_index = 0;
- int args_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
if (e->frame_type() == JS_FUNCTION) {
@@ -832,7 +792,7 @@
}
}
Translation translation(&translations_, frame_count, jsframe_count, zone());
- WriteTranslation(environment, &translation, &args_index, &args_count);
+ WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset();
environment->Register(deoptimization_index,
@@ -2802,8 +2762,7 @@
// root array to force relocation to be able to later patch with
// the cached map.
PredictableCodeSizeScope predictable(masm_, 5 * Assembler::kInstrSize);
- Handle<JSGlobalPropertyCell> cell =
- factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
+ Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
__ mov(ip, Operand(Handle<Object>(cell)));
__ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
__ cmp(map, Operand(ip));
@@ -2965,7 +2924,7 @@
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
Register result = ToRegister(instr->result());
__ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
- __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
@@ -3000,13 +2959,13 @@
if (instr->hydrogen()->RequiresHoleCheck()) {
// We use a temp to check the payload (CompareRoot might clobber ip).
Register payload = ToRegister(instr->temp());
- __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
__ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
DeoptimizeIf(eq, instr->environment());
}
// Store the value.
- __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset));
+ __ str(value, FieldMemOperand(cell, Cell::kValueOffset));
// Cells are always rescanned, so no write barrier here.
}
@@ -4219,8 +4178,26 @@
ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else if (instr->arity() == 1) {
+ Label done;
+ if (IsFastPackedElementsKind(kind)) {
+ Label packed_case;
+ // We might need a change here
+ // look at the first argument
+ __ ldr(r5, MemOperand(sp, 0));
+ __ cmp(r5, Operand::Zero());
+ __ b(eq, &packed_case);
+
+ ElementsKind holey_kind = GetHoleyElementsKind(kind);
+ ArraySingleArgumentConstructorStub stub(holey_kind,
+ disable_allocation_sites);
+ CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ jmp(&done);
+ __ bind(&packed_case);
+ }
+
ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ bind(&done);
} else {
ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4267,9 +4244,6 @@
}
if (!transition.is_null()) {
- if (transition->CanBeDeprecated()) {
- transition_maps_.Add(transition, info()->zone());
- }
__ mov(scratch, Operand(transition));
__ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
@@ -5279,10 +5253,9 @@
AllowDeferredHandleDereference smi_check;
if (isolate()->heap()->InNewSpace(*target)) {
Register reg = ToRegister(instr->value());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(target);
+ Handle<Cell> cell = isolate()->factory()->NewJSGlobalPropertyCell(target);
__ mov(ip, Operand(Handle<Object>(cell)));
- __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset));
__ cmp(reg, ip);
} else {
__ cmp(reg, Operand(target));
@@ -5382,11 +5355,7 @@
ASSERT(prototypes->length() == maps->length());
- if (instr->hydrogen()->CanOmitPrototypeChecks()) {
- for (int i = 0; i < maps->length(); i++) {
- prototype_maps_.Add(maps->at(i), info()->zone());
- }
- } else {
+ if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
for (int i = 0; i < prototypes->length(); i++) {
__ LoadHeapObject(prototype_reg, prototypes->at(i));
__ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index f264259..aeba5ea 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -56,8 +56,6 @@
deoptimizations_(4, info->zone()),
deopt_jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
- prototype_maps_(0, info->zone()),
- transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -173,10 +171,7 @@
int additional_offset);
// Emit frame translation commands for an environment.
- void WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* arguments_index,
- int* arguments_count);
+ void WriteTranslation(LEnvironment* environment, Translation* translation);
// Declare methods that deal with the individual node types.
#define DECLARE_DO(type) void Do##type(L##type* node);
@@ -295,10 +290,7 @@
void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -406,8 +398,6 @@
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
- ZoneList<Handle<Map> > prototype_maps_;
- ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index f3cfdc7..4b6eac2 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -400,10 +400,9 @@
Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
mov(result, Operand(cell));
- ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
+ ldr(result, FieldMemOperand(result, Cell::kValueOffset));
} else {
mov(result, Operand(object));
}
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 3595b52..1ccc106 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -427,12 +427,10 @@
Handle<Name> name,
Register scratch,
Label* miss) {
- Handle<JSGlobalPropertyCell> cell =
- GlobalObject::EnsurePropertyCell(global, name);
+ Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name);
ASSERT(cell->value()->IsTheHole());
__ mov(scratch, Operand(cell));
- __ ldr(scratch,
- FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(scratch, ip);
__ b(ne, miss);
@@ -1586,12 +1584,12 @@
void CallStubCompiler::GenerateLoadFunctionFromCell(
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Label* miss) {
// Get the value from the cell.
__ mov(r3, Operand(cell));
- __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(r1, FieldMemOperand(r3, Cell::kValueOffset));
// Check that the cell contains the same function.
if (heap()->InNewSpace(*function)) {
@@ -1662,7 +1660,7 @@
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1915,7 +1913,7 @@
Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1997,7 +1995,7 @@
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2079,7 +2077,7 @@
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2162,7 +2160,7 @@
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2234,7 +2232,7 @@
Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2342,7 +2340,7 @@
Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2441,7 +2439,7 @@
const CallOptimization& optimization,
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Counters* counters = isolate()->counters();
@@ -2613,7 +2611,7 @@
Handle<JSFunction> function) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
- Handle<JSGlobalPropertyCell>::null(),
+ Handle<Cell>::null(),
function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
@@ -2859,14 +2857,12 @@
// global object. We bail out to the runtime system to do that.
__ mov(scratch1(), Operand(cell));
__ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
- __ ldr(scratch3(),
- FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+ __ ldr(scratch3(), FieldMemOperand(scratch1(), Cell::kValueOffset));
__ cmp(scratch3(), scratch2());
__ b(eq, &miss);
// Store the value in the cell.
- __ str(value(),
- FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+ __ str(value(), FieldMemOperand(scratch1(), Cell::kValueOffset));
// Cells are always rescanned, so no write barrier here.
Counters* counters = isolate()->counters();
@@ -3002,7 +2998,7 @@
// Get the value from the cell.
__ mov(r3, Operand(cell));
- __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
+ __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
diff --git a/src/assembler.cc b/src/assembler.cc
index 6b0c4b8..626fd4f 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -724,7 +724,7 @@
// generation.
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
- RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+ RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::kApplyMask;
RelocIterator it(desc, mode_mask);
return !it.done();
@@ -754,8 +754,8 @@
return "code target";
case RelocInfo::CODE_TARGET_WITH_ID:
return "code target with id";
- case RelocInfo::GLOBAL_PROPERTY_CELL:
- return "global property cell";
+ case RelocInfo::CELL:
+ return "property cell";
case RelocInfo::RUNTIME_ENTRY:
return "runtime entry";
case RelocInfo::JS_RETURN:
@@ -830,7 +830,7 @@
case EMBEDDED_OBJECT:
Object::VerifyPointer(target_object());
break;
- case GLOBAL_PROPERTY_CELL:
+ case CELL:
Object::VerifyPointer(target_cell());
break;
case DEBUG_BREAK:
diff --git a/src/assembler.h b/src/assembler.h
index 2d9e727..f66f8bf 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -254,7 +254,7 @@
CODE_TARGET_CONTEXT, // Code target used for contextual loads and stores.
DEBUG_BREAK, // Code target for the debugger statement.
EMBEDDED_OBJECT,
- GLOBAL_PROPERTY_CELL,
+ CELL,
// Everything after runtime_entry (inclusive) is not GC'ed.
RUNTIME_ENTRY,
@@ -282,7 +282,7 @@
FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
LAST_CODE_ENUM = DEBUG_BREAK,
- LAST_GCED_ENUM = GLOBAL_PROPERTY_CELL,
+ LAST_GCED_ENUM = CELL,
// Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
@@ -386,9 +386,9 @@
INLINE(void set_target_runtime_entry(Address target,
WriteBarrierMode mode =
UPDATE_WRITE_BARRIER));
- INLINE(JSGlobalPropertyCell* target_cell());
- INLINE(Handle<JSGlobalPropertyCell> target_cell_handle());
- INLINE(void set_target_cell(JSGlobalPropertyCell* cell,
+ INLINE(Cell* target_cell());
+ INLINE(Handle<Cell> target_cell_handle());
+ INLINE(void set_target_cell(Cell* cell,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
INLINE(Code* code_age_stub());
INLINE(void set_code_age_stub(Code* stub));
diff --git a/src/ast.cc b/src/ast.cc
index a5d1e2d..0ebbd35 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -503,19 +503,7 @@
void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
- TypeInfo info = oracle->SwitchType(this);
- if (info.IsUninitialized()) info = TypeInfo::Unknown();
- if (info.IsSmi()) {
- compare_type_ = SMI_ONLY;
- } else if (info.IsInternalizedString()) {
- compare_type_ = NAME_ONLY;
- } else if (info.IsNonInternalizedString()) {
- compare_type_ = STRING_ONLY;
- } else if (info.IsNonPrimitive()) {
- compare_type_ = OBJECT_ONLY;
- } else {
- ASSERT(compare_type_ == NONE);
- }
+ compare_type_ = oracle->ClauseType(CompareId());
}
@@ -570,11 +558,11 @@
bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
LookupResult* lookup) {
target_ = Handle<JSFunction>::null();
- cell_ = Handle<JSGlobalPropertyCell>::null();
+ cell_ = Handle<Cell>::null();
ASSERT(lookup->IsFound() &&
lookup->type() == NORMAL &&
lookup->holder() == *global);
- cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
+ cell_ = Handle<Cell>(global->GetPropertyCell(lookup));
if (cell_->value()->IsJSFunction()) {
Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
// If the function is in new space we assume it's more likely to
@@ -685,17 +673,11 @@
}
+// TODO(rossberg): this function (and all other RecordTypeFeedback functions)
+// should disappear once we use the common type field in the AST consistently.
void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
- oracle->CompareType(this, &left_type_, &right_type_, &overall_type_);
- if (!overall_type_.IsUninitialized() && overall_type_.IsNonPrimitive() &&
- (op_ == Token::EQ || op_ == Token::EQ_STRICT)) {
- map_ = oracle->GetCompareMap(this);
- } else {
- // May be a compare to nil.
- map_ = oracle->CompareNilMonomorphicReceiverType(this);
- if (op_ != Token::EQ_STRICT)
- compare_nil_types_ = oracle->CompareNilTypes(this);
- }
+ oracle->CompareTypes(CompareOperationFeedbackId(),
+ &left_type_, &right_type_, &overall_type_, &compare_nil_type_);
}
@@ -1072,7 +1054,7 @@
: label_(label),
statements_(statements),
position_(pos),
- compare_type_(NONE),
+ compare_type_(Type::None(), isolate),
compare_id_(AstNode::GetNextId(isolate)),
entry_id_(AstNode::GetNextId(isolate)) {
}
diff --git a/src/ast.h b/src/ast.h
index 219a69b..b7ada60 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -358,6 +358,7 @@
// Expression type
Handle<Type> type() { return type_; }
+ void set_type(Handle<Type> type) { type_ = type; }
// Type feedback information for assignments and properties.
virtual bool IsMonomorphic() {
@@ -388,7 +389,7 @@
protected:
explicit Expression(Isolate* isolate)
- : type_(Type::Any(), isolate),
+ : type_(Type::None(), isolate),
id_(GetNextId(isolate)),
test_id_(GetNextId(isolate)) {}
@@ -1106,24 +1107,15 @@
// Type feedback information.
TypeFeedbackId CompareId() { return compare_id_; }
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
- bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
- bool IsNameCompare() { return compare_type_ == NAME_ONLY; }
- bool IsStringCompare() { return compare_type_ == STRING_ONLY; }
- bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
+ Handle<Type> compare_type() { return compare_type_; }
private:
Expression* label_;
Label body_target_;
ZoneList<Statement*>* statements_;
int position_;
- enum CompareTypeFeedback {
- NONE,
- SMI_ONLY,
- NAME_ONLY,
- STRING_ONLY,
- OBJECT_ONLY
- };
- CompareTypeFeedback compare_type_;
+ Handle<Type> compare_type_;
+
const TypeFeedbackId compare_id_;
const BailoutId entry_id_;
};
@@ -1705,7 +1697,7 @@
// as the holder!
Handle<JSObject> holder() { return holder_; }
- Handle<JSGlobalPropertyCell> cell() { return cell_; }
+ Handle<Cell> cell() { return cell_; }
bool ComputeTarget(Handle<Map> type, Handle<String> name);
bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult* lookup);
@@ -1745,7 +1737,7 @@
SmallMapList receiver_types_;
Handle<JSFunction> target_;
Handle<JSObject> holder_;
- Handle<JSGlobalPropertyCell> cell_;
+ Handle<Cell> cell_;
const BailoutId return_id_;
};
@@ -1765,7 +1757,7 @@
virtual bool IsMonomorphic() { return is_monomorphic_; }
Handle<JSFunction> target() const { return target_; }
ElementsKind elements_kind() const { return elements_kind_; }
- Handle<JSGlobalPropertyCell> allocation_info_cell() const {
+ Handle<Cell> allocation_info_cell() const {
return allocation_info_cell_;
}
@@ -1792,7 +1784,7 @@
bool is_monomorphic_;
Handle<JSFunction> target_;
ElementsKind elements_kind_;
- Handle<JSGlobalPropertyCell> allocation_info_cell_;
+ Handle<Cell> allocation_info_cell_;
const BailoutId return_id_;
};
@@ -2003,11 +1995,10 @@
// Type feedback information.
TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); }
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
- TypeInfo left_type() const { return left_type_; }
- TypeInfo right_type() const { return right_type_; }
- TypeInfo overall_type() const { return overall_type_; }
- byte compare_nil_types() const { return compare_nil_types_; }
- Handle<Map> map() const { return map_; }
+ Handle<Type> left_type() const { return left_type_; }
+ Handle<Type> right_type() const { return right_type_; }
+ Handle<Type> overall_type() const { return overall_type_; }
+ Handle<Type> compare_nil_type() const { return compare_nil_type_; }
// Match special cases.
bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
@@ -2034,11 +2025,10 @@
Expression* right_;
int pos_;
- TypeInfo left_type_;
- TypeInfo right_type_;
- TypeInfo overall_type_;
- byte compare_nil_types_;
- Handle<Map> map_;
+ Handle<Type> left_type_;
+ Handle<Type> right_type_;
+ Handle<Type> overall_type_;
+ Handle<Type> compare_nil_type_;
};
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index a51a9b1..0b39faa 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2499,6 +2499,7 @@
Handle<Name> key = Handle<Name>(Name::cast(raw_key));
Handle<Object> value = Handle<Object>(properties->ValueAt(i),
isolate());
+ ASSERT(!value->IsCell());
if (value->IsJSGlobalPropertyCell()) {
value = Handle<Object>(JSGlobalPropertyCell::cast(*value)->value(),
isolate());
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 99c4db5..e1e25fb 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -733,12 +733,13 @@
template <>
HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
+ Isolate* isolate = graph()->isolate();
CompareNilICStub* stub = casted_stub();
HIfContinuation continuation;
- Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
- BuildCompareNil(GetParameter(0),
- stub->GetTypes(), sentinel_map,
- RelocInfo::kNoPosition, &continuation);
+ Handle<Map> sentinel_map(isolate->heap()->meta_map());
+ Handle<Type> type =
+ CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map);
+ BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
IfBuilder if_nil(this, &continuation);
if_nil.Then();
if (continuation.IsFalseReachable()) {
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 6b6e250..5bec7e0 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -431,24 +431,24 @@
void CompareNilICStub::Record(Handle<Object> object) {
- ASSERT(types_ != Types::FullCompare());
+ ASSERT(state_ != State::Generic());
if (object->IsNull()) {
- types_.Add(NULL_TYPE);
+ state_.Add(NULL_TYPE);
} else if (object->IsUndefined()) {
- types_.Add(UNDEFINED);
+ state_.Add(UNDEFINED);
} else if (object->IsUndetectableObject() ||
object->IsOddball() ||
!object->IsHeapObject()) {
- types_ = Types::FullCompare();
+ state_ = State::Generic();
} else if (IsMonomorphic()) {
- types_ = Types::FullCompare();
+ state_ = State::Generic();
} else {
- types_.Add(MONOMORPHIC_MAP);
+ state_.Add(MONOMORPHIC_MAP);
}
}
-void CompareNilICStub::Types::TraceTransition(Types to) const {
+void CompareNilICStub::State::TraceTransition(State to) const {
#ifdef DEBUG
if (!FLAG_trace_ic) return;
char buffer[100];
@@ -467,13 +467,13 @@
void CompareNilICStub::PrintName(StringStream* stream) {
stream->Add("CompareNilICStub_");
- types_.Print(stream);
+ state_.Print(stream);
stream->Add((nil_value_ == kNullValue) ? "(NullValue|":
"(UndefinedValue|");
}
-void CompareNilICStub::Types::Print(StringStream* stream) const {
+void CompareNilICStub::State::Print(StringStream* stream) const {
stream->Add("(");
SimpleListPrinter printer(stream);
if (IsEmpty()) printer.Add("None");
@@ -481,10 +481,40 @@
if (Contains(NULL_TYPE)) printer.Add("Null");
if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap");
if (Contains(UNDETECTABLE)) printer.Add("Undetectable");
+ if (Contains(GENERIC)) printer.Add("Generic");
stream->Add(")");
}
+Handle<Type> CompareNilICStub::StateToType(
+ Isolate* isolate,
+ State state,
+ Handle<Map> map) {
+ if (state.Contains(CompareNilICStub::GENERIC)) {
+ return handle(Type::Any(), isolate);
+ }
+
+ Handle<Type> result(Type::None(), isolate);
+ if (state.Contains(CompareNilICStub::UNDEFINED)) {
+ result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
+ isolate);
+ }
+ if (state.Contains(CompareNilICStub::NULL_TYPE)) {
+ result = handle(Type::Union(result, handle(Type::Null(), isolate)),
+ isolate);
+ }
+ if (state.Contains(CompareNilICStub::UNDETECTABLE)) {
+ result = handle(Type::Union(result, handle(Type::Undetectable(), isolate)),
+ isolate);
+ } else if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
+ Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
+ result = handle(Type::Union(result, handle(type, isolate)), isolate);
+ }
+
+ return result;
+}
+
+
void InstanceofStub::PrintName(StringStream* stream) {
const char* args = "";
if (HasArgsInRegisters()) {
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 0ea7ac9..edbc93d 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -1124,46 +1124,50 @@
class CompareNilICStub : public HydrogenCodeStub {
public:
- enum Type {
+ enum CompareNilType {
UNDEFINED,
NULL_TYPE,
MONOMORPHIC_MAP,
UNDETECTABLE,
+ GENERIC,
NUMBER_OF_TYPES
};
- class Types : public EnumSet<Type, byte> {
+ class State : public EnumSet<CompareNilType, byte> {
public:
- Types() : EnumSet<Type, byte>(0) { }
- explicit Types(byte bits) : EnumSet<Type, byte>(bits) { }
+ State() : EnumSet<CompareNilType, byte>(0) { }
+ explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
- static Types FullCompare() {
- Types set;
+ static State Generic() {
+ State set;
set.Add(UNDEFINED);
set.Add(NULL_TYPE);
set.Add(UNDETECTABLE);
+ set.Add(GENERIC);
return set;
}
void Print(StringStream* stream) const;
- void TraceTransition(Types to) const;
+ void TraceTransition(State to) const;
};
+ static Handle<Type> StateToType(
+ Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
+
// At most 6 different types can be distinguished, because the Code object
// only has room for a single byte to hold a set and there are two more
// boolean flags we need to store. :-P
STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
- CompareNilICStub(NilValue nil, Types types = Types())
- : types_(types) {
- nil_value_ = nil;
+ CompareNilICStub(NilValue nil, State state = State())
+ : nil_value_(nil), state_(state) {
}
CompareNilICStub(Code::ExtraICState ic_state,
InitializationState init_state = INITIALIZED)
: HydrogenCodeStub(init_state) {
nil_value_ = NilValueField::decode(ic_state);
- types_ = Types(ExtractTypesFromExtraICState(ic_state));
+ state_ = State(ExtractTypesFromExtraICState(ic_state));
}
static Handle<Code> GetUninitialized(Isolate* isolate,
@@ -1183,9 +1187,9 @@
}
virtual InlineCacheState GetICState() {
- if (types_ == Types::FullCompare()) {
+ if (state_ == State::Generic()) {
return MEGAMORPHIC;
- } else if (types_.Contains(MONOMORPHIC_MAP)) {
+ } else if (state_.Contains(MONOMORPHIC_MAP)) {
return MONOMORPHIC;
} else {
return PREMONOMORPHIC;
@@ -1198,20 +1202,18 @@
// extra ic state = nil_value | type_n-1 | ... | type_0
virtual Code::ExtraICState GetExtraICState() {
- return NilValueField::encode(nil_value_) |
- types_.ToIntegral();
+ return NilValueField::encode(nil_value_) | state_.ToIntegral();
}
- static byte ExtractTypesFromExtraICState(
- Code::ExtraICState state) {
+ static byte ExtractTypesFromExtraICState(Code::ExtraICState state) {
return state & ((1 << NUMBER_OF_TYPES) - 1);
}
void Record(Handle<Object> object);
- bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); }
+ bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); }
NilValue GetNilValue() const { return nil_value_; }
- Types GetTypes() const { return types_; }
- void ClearTypes() { types_.RemoveAll(); }
+ State GetState() const { return state_; }
+ void ClearState() { state_.RemoveAll(); }
virtual void PrintName(StringStream* stream);
@@ -1229,7 +1231,7 @@
virtual int NotMissMinorKey() { return GetExtraICState(); }
NilValue nil_value_;
- Types types_;
+ State state_;
DISALLOW_COPY_AND_ASSIGN(CompareNilICStub);
};
diff --git a/src/compiler.cc b/src/compiler.cc
index 5fc107f..5de9d96 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -106,6 +106,9 @@
opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
? new List<OffsetRange>(2) : NULL;
+ for (int i = 0; i < DependentCode::kGroupCount; i++) {
+ dependent_maps_[i] = NULL;
+ }
if (mode == STUB) {
mode_ = STUB;
return;
@@ -125,6 +128,41 @@
CompilationInfo::~CompilationInfo() {
delete deferred_handles_;
delete no_frame_ranges_;
+#ifdef DEBUG
+ // Check that no dependent maps have been added or added dependent maps have
+ // been rolled back or committed.
+ for (int i = 0; i < DependentCode::kGroupCount; i++) {
+ ASSERT_EQ(NULL, dependent_maps_[i]);
+ }
+#endif // DEBUG
+}
+
+
+void CompilationInfo::CommitDependentMaps(Handle<Code> code) {
+ for (int i = 0; i < DependentCode::kGroupCount; i++) {
+ ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
+ if (group_maps == NULL) continue;
+ ASSERT(!object_wrapper_.is_null());
+ for (int j = 0; j < group_maps->length(); j++) {
+ group_maps->at(j)->dependent_code()->UpdateToFinishedCode(
+ static_cast<DependentCode::DependencyGroup>(i), this, *code);
+ }
+ dependent_maps_[i] = NULL; // Zone-allocated, no need to delete.
+ }
+}
+
+
+void CompilationInfo::RollbackDependentMaps() {
+ // Unregister from all dependent maps if not yet committed.
+ for (int i = 0; i < DependentCode::kGroupCount; i++) {
+ ZoneList<Handle<Map> >* group_maps = dependent_maps_[i];
+ if (group_maps == NULL) continue;
+ for (int j = 0; j < group_maps->length(); j++) {
+ group_maps->at(j)->dependent_code()->RemoveCompilationInfo(
+ static_cast<DependentCode::DependencyGroup>(i), this);
+ }
+ dependent_maps_[i] = NULL; // Zone-allocated, no need to delete.
+ }
}
@@ -364,7 +402,7 @@
}
// Type-check the function.
- AstTyper::Type(info());
+ AstTyper::Run(info());
graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());
@@ -982,7 +1020,7 @@
// The function may have already been optimized by OSR. Simply continue.
// Except when OSR already disabled optimization for some reason.
if (info->shared_info()->optimization_disabled()) {
- info->SetCode(Handle<Code>(info->shared_info()->code()));
+ info->AbortOptimization();
InstallFullCode(*info);
if (FLAG_trace_parallel_recompilation) {
PrintF(" ** aborting optimization for ");
@@ -1000,9 +1038,11 @@
// If crankshaft succeeded, install the optimized code else install
// the unoptimized code.
OptimizingCompiler::Status status = optimizing_compiler->last_status();
- if (status != OptimizingCompiler::SUCCEEDED) {
- optimizing_compiler->info()->set_bailout_reason(
- "failed/bailed out last time");
+ if (info->HasAbortedDueToDependentMap()) {
+ info->set_bailout_reason("bailed out due to dependent map");
+ status = optimizing_compiler->AbortOptimization();
+ } else if (status != OptimizingCompiler::SUCCEEDED) {
+ info->set_bailout_reason("failed/bailed out last time");
status = optimizing_compiler->AbortOptimization();
} else {
status = optimizing_compiler->GenerateAndInstallCode();
@@ -1141,7 +1181,16 @@
Handle<Code> code = info->code();
if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
return;
+ Handle<String> script_name;
if (script->name()->IsString()) {
+ script_name = Handle<String>(String::cast(script->name()));
+ } else {
+ Handle<Object> name = GetScriptNameOrSourceURL(script);
+ if (!name.is_null() && name->IsString()) {
+ script_name = Handle<String>::cast(name);
+ }
+ }
+ if (!script_name.is_null()) {
int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
USE(line_num);
PROFILE(info->isolate(),
@@ -1149,7 +1198,7 @@
*code,
*shared,
info,
- String::cast(script->name()),
+ String::cast(*script_name),
line_num));
} else {
PROFILE(info->isolate(),
diff --git a/src/compiler.h b/src/compiler.h
index 8e6d295..f53feb9 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -57,12 +57,8 @@
// is constructed based on the resources available at compile-time.
class CompilationInfo {
public:
- CompilationInfo(Handle<Script> script, Zone* zone);
- CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
CompilationInfo(Handle<JSFunction> closure, Zone* zone);
- CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate, Zone* zone);
-
- ~CompilationInfo();
+ virtual ~CompilationInfo();
Isolate* isolate() {
ASSERT(Isolate::Current() == isolate_);
@@ -243,6 +239,17 @@
deferred_handles_ = deferred_handles;
}
+ ZoneList<Handle<Map> >* dependent_maps(DependentCode::DependencyGroup group) {
+ if (dependent_maps_[group] == NULL) {
+ dependent_maps_[group] = new(zone_) ZoneList<Handle<Map> >(2, zone_);
+ }
+ return dependent_maps_[group];
+ }
+
+ void CommitDependentMaps(Handle<Code> code);
+
+ void RollbackDependentMaps();
+
void SaveHandles() {
SaveHandle(&closure_);
SaveHandle(&shared_info_);
@@ -276,6 +283,26 @@
return result;
}
+ Handle<Foreign> object_wrapper() {
+ if (object_wrapper_.is_null()) {
+ object_wrapper_ =
+ isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
+ }
+ return object_wrapper_;
+ }
+
+ void AbortDueToDependentMap() {
+ mode_ = DEPENDENT_MAP_ABORT;
+ }
+
+ bool HasAbortedDueToDependentMap() {
+ return mode_ == DEPENDENT_MAP_ABORT;
+ }
+
+ protected:
+ CompilationInfo(Handle<Script> script, Zone* zone);
+ CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
+ CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate, Zone* zone);
private:
Isolate* isolate_;
@@ -289,7 +316,8 @@
BASE,
OPTIMIZE,
NONOPT,
- STUB
+ STUB,
+ DEPENDENT_MAP_ABORT
};
void Initialize(Isolate* isolate, Mode mode, Zone* zone);
@@ -369,6 +397,8 @@
DeferredHandles* deferred_handles_;
+ ZoneList<Handle<Map> >* dependent_maps_[DependentCode::kGroupCount];
+
template<typename T>
void SaveHandle(Handle<T> *object) {
if (!object->is_null()) {
@@ -387,6 +417,8 @@
// during graph optimization.
int opt_count_;
+ Handle<Foreign> object_wrapper_;
+
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
@@ -407,11 +439,18 @@
: CompilationInfo(closure, &zone_),
zone_(closure->GetIsolate()),
zone_scope_(&zone_, DELETE_ON_EXIT) {}
- explicit CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
+ CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
: CompilationInfo(stub, isolate, &zone_),
zone_(isolate),
zone_scope_(&zone_, DELETE_ON_EXIT) {}
+ // Virtual destructor because a CompilationInfoWithZone has to exit the
+ // zone scope and get rid of dependent maps even when the destructor is
+ // called when cast as a CompilationInfo.
+ virtual ~CompilationInfoWithZone() {
+ RollbackDependentMaps();
+ }
+
private:
Zone zone_;
ZoneScope zone_scope_;
diff --git a/src/data-flow.h b/src/data-flow.h
index 7eeb794..8ceccf6 100644
--- a/src/data-flow.h
+++ b/src/data-flow.h
@@ -215,6 +215,8 @@
};
GrowableBitVector() : bits_(NULL) { }
+ GrowableBitVector(int length, Zone* zone)
+ : bits_(new(zone) BitVector(length, zone)) { }
bool Contains(int value) const {
if (!InBitsRange(value)) return false;
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 723d3f6..14c1d73 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -534,8 +534,9 @@
output_count_(0),
jsframe_count_(0),
output_(NULL),
- deferred_arguments_objects_values_(0),
- deferred_arguments_objects_(0),
+ deferred_objects_tagged_values_(0),
+ deferred_objects_double_values_(0),
+ deferred_objects_(0),
deferred_heap_numbers_(0),
trace_(false) {
// For COMPILED_STUBs called from builtins, the function pointer is a SMI
@@ -1566,15 +1567,14 @@
void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
ASSERT_NE(DEBUGGER, bailout_type_);
- // Handlify all argument object values before triggering any allocation.
- List<Handle<Object> > values(deferred_arguments_objects_values_.length());
- for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) {
- values.Add(Handle<Object>(deferred_arguments_objects_values_[i],
- isolate_));
+ // Handlify all tagged object values before triggering any allocation.
+ List<Handle<Object> > values(deferred_objects_tagged_values_.length());
+ for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
+ values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
}
// Play it safe and clear all unhandlified values before we continue.
- deferred_arguments_objects_values_.Clear();
+ deferred_objects_tagged_values_.Clear();
// Materialize all heap numbers before looking at arguments because when the
// output frames are used to materialize arguments objects later on they need
@@ -1591,6 +1591,18 @@
Memory::Object_at(d.slot_address()) = *num;
}
+ // Materialize all heap numbers required for arguments objects.
+ for (int i = 0; i < values.length(); i++) {
+ if (!values.at(i)->IsTheHole()) continue;
+ double double_value = deferred_objects_double_values_[i];
+ Handle<Object> num = isolate_->factory()->NewNumber(double_value);
+ if (trace_) {
+ PrintF("Materializing a new heap number %p [%e] for arguments object\n",
+ reinterpret_cast<void*>(*num), double_value);
+ }
+ values.Set(i, num);
+ }
+
// Materialize arguments objects one frame at a time.
for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
if (frame_index != 0) it->Advance();
@@ -1599,9 +1611,9 @@
Handle<JSObject> arguments;
for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) {
- ArgumentsObjectMaterializationDescriptor descriptor =
- deferred_arguments_objects_.RemoveLast();
- const int length = descriptor.arguments_length();
+ ObjectMaterializationDescriptor descriptor =
+ deferred_objects_.RemoveLast();
+ const int length = descriptor.object_length();
if (arguments.is_null()) {
if (frame->has_adapted_arguments()) {
// Use the arguments adapter frame we just built to materialize the
@@ -1695,7 +1707,7 @@
#endif
-static const char* TraceValueType(bool is_smi, bool is_native) {
+static const char* TraceValueType(bool is_smi, bool is_native = false) {
if (is_native) {
return "native";
} else if (is_smi) {
@@ -1706,6 +1718,204 @@
}
+void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
+ int object_opcode,
+ int field_index) {
+ disasm::NameConverter converter;
+ Address object_slot = deferred_objects_.last().slot_address();
+
+ // Ignore commands marked as duplicate and act on the first non-duplicate.
+ Translation::Opcode opcode =
+ static_cast<Translation::Opcode>(iterator->Next());
+ while (opcode == Translation::DUPLICATE) {
+ opcode = static_cast<Translation::Opcode>(iterator->Next());
+ iterator->Skip(Translation::NumberOfOperandsFor(opcode));
+ opcode = static_cast<Translation::Opcode>(iterator->Next());
+ }
+
+ switch (opcode) {
+ case Translation::BEGIN:
+ case Translation::JS_FRAME:
+ case Translation::ARGUMENTS_ADAPTOR_FRAME:
+ case Translation::CONSTRUCT_STUB_FRAME:
+ case Translation::GETTER_STUB_FRAME:
+ case Translation::SETTER_STUB_FRAME:
+ case Translation::COMPILED_STUB_FRAME:
+ case Translation::ARGUMENTS_OBJECT:
+ case Translation::DUPLICATE:
+ UNREACHABLE();
+ return;
+
+ case Translation::REGISTER: {
+ int input_reg = iterator->Next();
+ intptr_t input_value = input_->GetRegister(input_reg);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("0x%08" V8PRIxPTR " ; %s ", input_value,
+ converter.NameOfCPURegister(input_reg));
+ reinterpret_cast<Object*>(input_value)->ShortPrint();
+ PrintF("\n");
+ }
+ AddObjectTaggedValue(input_value);
+ return;
+ }
+
+ case Translation::INT32_REGISTER: {
+ int input_reg = iterator->Next();
+ intptr_t value = input_->GetRegister(input_reg);
+ bool is_smi = Smi::IsValid(value);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%" V8PRIdPTR " ; %s (%s)\n", value,
+ converter.NameOfCPURegister(input_reg),
+ TraceValueType(is_smi));
+ }
+ if (is_smi) {
+ intptr_t tagged_value =
+ reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+ AddObjectTaggedValue(tagged_value);
+ } else {
+ double double_value = static_cast<double>(static_cast<int32_t>(value));
+ AddObjectDoubleValue(double_value);
+ }
+ return;
+ }
+
+ case Translation::UINT32_REGISTER: {
+ int input_reg = iterator->Next();
+ uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
+ bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%" V8PRIdPTR " ; uint %s (%s)\n", value,
+ converter.NameOfCPURegister(input_reg),
+ TraceValueType(is_smi));
+ }
+ if (is_smi) {
+ intptr_t tagged_value =
+ reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+ AddObjectTaggedValue(tagged_value);
+ } else {
+ double double_value = static_cast<double>(static_cast<uint32_t>(value));
+ AddObjectDoubleValue(double_value);
+ }
+ return;
+ }
+
+ case Translation::DOUBLE_REGISTER: {
+ int input_reg = iterator->Next();
+ double value = input_->GetDoubleRegister(input_reg);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%e ; %s\n", value,
+ DoubleRegister::AllocationIndexToString(input_reg));
+ }
+ AddObjectDoubleValue(value);
+ return;
+ }
+
+ case Translation::STACK_SLOT: {
+ int input_slot_index = iterator->Next();
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+ intptr_t input_value = input_->GetFrameSlot(input_offset);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
+ reinterpret_cast<Object*>(input_value)->ShortPrint();
+ PrintF("\n");
+ }
+ AddObjectTaggedValue(input_value);
+ return;
+ }
+
+ case Translation::INT32_STACK_SLOT: {
+ int input_slot_index = iterator->Next();
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+ intptr_t value = input_->GetFrameSlot(input_offset);
+ bool is_smi = Smi::IsValid(value);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%" V8PRIdPTR " ; [sp + %d] (%s)\n",
+ value, input_offset, TraceValueType(is_smi));
+ }
+ if (is_smi) {
+ intptr_t tagged_value =
+ reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+ AddObjectTaggedValue(tagged_value);
+ } else {
+ double double_value = static_cast<double>(static_cast<int32_t>(value));
+ AddObjectDoubleValue(double_value);
+ }
+ return;
+ }
+
+ case Translation::UINT32_STACK_SLOT: {
+ int input_slot_index = iterator->Next();
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+ uintptr_t value =
+ static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
+ bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%" V8PRIdPTR " ; [sp + %d] (uint %s)\n",
+ value, input_offset, TraceValueType(is_smi));
+ }
+ if (is_smi) {
+ intptr_t tagged_value =
+ reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
+ AddObjectTaggedValue(tagged_value);
+ } else {
+ double double_value = static_cast<double>(static_cast<uint32_t>(value));
+ AddObjectDoubleValue(double_value);
+ }
+ return;
+ }
+
+ case Translation::DOUBLE_STACK_SLOT: {
+ int input_slot_index = iterator->Next();
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
+ double value = input_->GetDoubleFrameSlot(input_offset);
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ PrintF("%e ; [sp + %d]\n", value, input_offset);
+ }
+ AddObjectDoubleValue(value);
+ return;
+ }
+
+ case Translation::LITERAL: {
+ Object* literal = ComputeLiteral(iterator->Next());
+ if (trace_) {
+ PrintF(" object @0x%08" V8PRIxPTR ": [field #%d] <- ",
+ reinterpret_cast<intptr_t>(object_slot),
+ field_index);
+ literal->ShortPrint();
+ PrintF(" ; literal\n");
+ }
+ intptr_t value = reinterpret_cast<intptr_t>(literal);
+ AddObjectTaggedValue(value);
+ return;
+ }
+ }
+}
+
+
void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
int frame_index,
unsigned output_offset,
@@ -1758,7 +1968,6 @@
intptr_t value = input_->GetRegister(input_reg);
bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
Smi::IsValid(value);
-
if (trace_) {
PrintF(
" 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
@@ -1836,8 +2045,7 @@
case Translation::STACK_SLOT: {
int input_slot_index = iterator->Next();
- unsigned input_offset =
- input_->GetOffsetFromSlotIndex(input_slot_index);
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
intptr_t input_value = input_->GetFrameSlot(input_offset);
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": ",
@@ -1855,8 +2063,7 @@
case Translation::INT32_STACK_SLOT: {
int input_slot_index = iterator->Next();
- unsigned input_offset =
- input_->GetOffsetFromSlotIndex(input_slot_index);
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
intptr_t value = input_->GetFrameSlot(input_offset);
bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
Smi::IsValid(value);
@@ -1888,8 +2095,7 @@
case Translation::UINT32_STACK_SLOT: {
int input_slot_index = iterator->Next();
- unsigned input_offset =
- input_->GetOffsetFromSlotIndex(input_slot_index);
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
uintptr_t value =
static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
@@ -1922,8 +2128,7 @@
case Translation::DOUBLE_STACK_SLOT: {
int input_slot_index = iterator->Next();
- unsigned input_offset =
- input_->GetOffsetFromSlotIndex(input_slot_index);
+ unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
double value = input_->GetDoubleFrameSlot(input_offset);
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
@@ -1954,31 +2159,24 @@
}
case Translation::ARGUMENTS_OBJECT: {
- bool args_known = iterator->Next();
- int args_index = iterator->Next() + 1; // Skip receiver.
- int args_length = iterator->Next() - 1; // Skip receiver.
+ int length = iterator->Next();
if (trace_) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
output_[frame_index]->GetTop() + output_offset,
output_offset);
isolate_->heap()->arguments_marker()->ShortPrint();
- PrintF(" ; %sarguments object\n", args_known ? "" : "dummy ");
+ PrintF(" ; arguments object (length = %d)\n", length);
}
// Use the arguments marker value as a sentinel and fill in the arguments
// object after the deoptimized frame is built.
intptr_t value = reinterpret_cast<intptr_t>(
isolate_->heap()->arguments_marker());
- AddArgumentsObject(
- output_[frame_index]->GetTop() + output_offset, args_length);
+ AddObjectStart(output_[frame_index]->GetTop() + output_offset, length);
output_[frame_index]->SetFrameSlot(output_offset, value);
- // We save the tagged argument values on the side and materialize the
- // actual arguments object after the deoptimized frame is built.
- for (int i = 0; i < args_length; i++) {
- unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i);
- intptr_t input_value = args_known
- ? input_->GetFrameSlot(input_offset)
- : reinterpret_cast<intptr_t>(isolate_->heap()->the_hole_value());
- AddArgumentsObjectValue(input_value);
+ // We save the argument values on the side and materialize the actual
+ // arguments object after the deoptimized frame is built.
+ for (int i = 0; i < length; i++) {
+ DoTranslateObject(iterator, Translation::ARGUMENTS_OBJECT, i);
}
return;
}
@@ -2324,15 +2522,22 @@
}
-void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) {
- ArgumentsObjectMaterializationDescriptor object_desc(
- reinterpret_cast<Address>(slot_address), argc);
- deferred_arguments_objects_.Add(object_desc);
+void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
+ ObjectMaterializationDescriptor object_desc(
+ reinterpret_cast<Address>(slot_address), length);
+ deferred_objects_.Add(object_desc);
}
-void Deoptimizer::AddArgumentsObjectValue(intptr_t value) {
- deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value));
+void Deoptimizer::AddObjectTaggedValue(intptr_t value) {
+ deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
+ deferred_objects_double_values_.Add(isolate()->heap()->nan_value()->value());
+}
+
+
+void Deoptimizer::AddObjectDoubleValue(double value) {
+ deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
+ deferred_objects_double_values_.Add(value);
}
@@ -2556,6 +2761,12 @@
}
+void Translation::BeginArgumentsObject(int args_length) {
+ buffer_->Add(ARGUMENTS_OBJECT, zone());
+ buffer_->Add(args_length, zone());
+}
+
+
void Translation::StoreRegister(Register reg) {
buffer_->Add(REGISTER, zone());
buffer_->Add(reg.code(), zone());
@@ -2610,16 +2821,6 @@
}
-void Translation::StoreArgumentsObject(bool args_known,
- int args_index,
- int args_length) {
- buffer_->Add(ARGUMENTS_OBJECT, zone());
- buffer_->Add(args_known, zone());
- buffer_->Add(args_index, zone());
- buffer_->Add(args_length, zone());
-}
-
-
void Translation::MarkDuplicate() {
buffer_->Add(DUPLICATE, zone());
}
@@ -2631,6 +2832,7 @@
return 0;
case GETTER_STUB_FRAME:
case SETTER_STUB_FRAME:
+ case ARGUMENTS_OBJECT:
case REGISTER:
case INT32_REGISTER:
case UINT32_REGISTER:
@@ -2647,7 +2849,6 @@
case CONSTRUCT_STUB_FRAME:
return 2;
case JS_FRAME:
- case ARGUMENTS_OBJECT:
return 3;
}
UNREACHABLE();
diff --git a/src/deoptimizer.h b/src/deoptimizer.h
index 5569f7f..5ca635c 100644
--- a/src/deoptimizer.h
+++ b/src/deoptimizer.h
@@ -75,17 +75,17 @@
};
-class ArgumentsObjectMaterializationDescriptor BASE_EMBEDDED {
+class ObjectMaterializationDescriptor BASE_EMBEDDED {
public:
- ArgumentsObjectMaterializationDescriptor(Address slot_address, int argc)
- : slot_address_(slot_address), arguments_length_(argc) { }
+ ObjectMaterializationDescriptor(Address slot_address, int length)
+ : slot_address_(slot_address), object_length_(length) { }
Address slot_address() const { return slot_address_; }
- int arguments_length() const { return arguments_length_; }
+ int object_length() const { return object_length_; }
private:
Address slot_address_;
- int arguments_length_;
+ int object_length_;
};
@@ -369,6 +369,10 @@
void DoComputeCompiledStubFrame(TranslationIterator* iterator,
int frame_index);
+ void DoTranslateObject(TranslationIterator* iterator,
+ int object_opcode,
+ int field_index);
+
enum DeoptimizerTranslatedValueType {
TRANSLATED_VALUE_IS_NATIVE,
TRANSLATED_VALUE_IS_TAGGED
@@ -394,8 +398,9 @@
Object* ComputeLiteral(int index) const;
- void AddArgumentsObject(intptr_t slot_address, int argc);
- void AddArgumentsObjectValue(intptr_t value);
+ void AddObjectStart(intptr_t slot_address, int argc);
+ void AddObjectTaggedValue(intptr_t value);
+ void AddObjectDoubleValue(double value);
void AddDoubleValue(intptr_t slot_address, double value);
static void GenerateDeoptimizationEntries(
@@ -446,8 +451,9 @@
// Array of output frame descriptions.
FrameDescription** output_;
- List<Object*> deferred_arguments_objects_values_;
- List<ArgumentsObjectMaterializationDescriptor> deferred_arguments_objects_;
+ List<Object*> deferred_objects_tagged_values_;
+ List<double> deferred_objects_double_values_;
+ List<ObjectMaterializationDescriptor> deferred_objects_;
List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_;
#ifdef DEBUG
DisallowHeapAllocation* disallow_heap_allocation_;
@@ -698,6 +704,7 @@
SETTER_STUB_FRAME,
ARGUMENTS_ADAPTOR_FRAME,
COMPILED_STUB_FRAME,
+ ARGUMENTS_OBJECT,
REGISTER,
INT32_REGISTER,
UINT32_REGISTER,
@@ -707,7 +714,6 @@
UINT32_STACK_SLOT,
DOUBLE_STACK_SLOT,
LITERAL,
- ARGUMENTS_OBJECT,
// A prefix indicating that the next command is a duplicate of the one
// that follows it.
@@ -733,6 +739,7 @@
void BeginConstructStubFrame(int literal_id, unsigned height);
void BeginGetterStubFrame(int literal_id);
void BeginSetterStubFrame(int literal_id);
+ void BeginArgumentsObject(int args_length);
void StoreRegister(Register reg);
void StoreInt32Register(Register reg);
void StoreUint32Register(Register reg);
@@ -742,7 +749,6 @@
void StoreUint32StackSlot(int index);
void StoreDoubleStackSlot(int index);
void StoreLiteral(int literal_id);
- void StoreArgumentsObject(bool args_known, int args_index, int args_length);
void MarkDuplicate();
Zone* zone() const { return zone_; }
diff --git a/src/extensions/statistics-extension.cc b/src/extensions/statistics-extension.cc
index e5a3009..32bc07d 100644
--- a/src/extensions/statistics-extension.cc
+++ b/src/extensions/statistics-extension.cc
@@ -133,6 +133,12 @@
"cell_space_available_bytes");
AddNumber(result, heap->cell_space()->CommittedMemory(),
"cell_space_commited_bytes");
+ AddNumber(result, heap->property_cell_space()->Size(),
+ "property_cell_space_live_bytes");
+ AddNumber(result, heap->property_cell_space()->Available(),
+ "property_cell_space_available_bytes");
+ AddNumber(result, heap->property_cell_space()->CommittedMemory(),
+ "property_cell_space_commited_bytes");
AddNumber(result, heap->lo_space()->Size(),
"lo_space_live_bytes");
AddNumber(result, heap->lo_space()->Available(),
diff --git a/src/factory.cc b/src/factory.cc
index c47b57d..fbe6cb8 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -482,6 +482,15 @@
}
+Handle<Cell> Factory::NewCell(Handle<Object> value) {
+ AllowDeferredHandleDereference convert_to_cell;
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->AllocateCell(*value),
+ Cell);
+}
+
+
Handle<JSGlobalPropertyCell> Factory::NewJSGlobalPropertyCell(
Handle<Object> value) {
AllowDeferredHandleDereference convert_to_cell;
diff --git a/src/factory.h b/src/factory.h
index d59d742..07ce96e 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -235,6 +235,8 @@
void* external_pointer,
PretenureFlag pretenure = NOT_TENURED);
+ Handle<Cell> NewCell(Handle<Object> value);
+
Handle<JSGlobalPropertyCell> NewJSGlobalPropertyCell(
Handle<Object> value);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index b70a532..49dac4a 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -178,8 +178,7 @@
DEFINE_implication(harmony, harmony_proxies)
DEFINE_implication(harmony, harmony_collections)
DEFINE_implication(harmony, harmony_observation)
-// TODO(wingo): Re-enable when GC bug that appeared in r15060 is gone.
-// DEFINE_implication(harmony, harmony_generators)
+DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony, harmony_iteration)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index bad634c..49a3194 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -473,7 +473,7 @@
void FullCodeGenerator::RecordTypeFeedbackCell(
- TypeFeedbackId id, Handle<JSGlobalPropertyCell> cell) {
+ TypeFeedbackId id, Handle<Cell> cell) {
TypeFeedbackCellEntry entry = { id, cell };
type_feedback_cells_.Add(entry, zone());
}
@@ -1230,13 +1230,7 @@
}
-void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
- Comment cmnt(masm_, "[ ReturnStatement");
- SetStatementPosition(stmt);
- Expression* expr = stmt->expression();
- VisitForAccumulatorValue(expr);
-
- // Exit all nested statements.
+void FullCodeGenerator::EmitUnwindBeforeReturn() {
NestedStatement* current = nesting_stack_;
int stack_depth = 0;
int context_length = 0;
@@ -1244,7 +1238,15 @@
current = current->Exit(&stack_depth, &context_length);
}
__ Drop(stack_depth);
+}
+
+void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
+ Comment cmnt(masm_, "[ ReturnStatement");
+ SetStatementPosition(stmt);
+ Expression* expr = stmt->expression();
+ VisitForAccumulatorValue(expr);
+ EmitUnwindBeforeReturn();
EmitReturnSequence();
}
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 68263a5..969a98d 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -410,10 +410,10 @@
// this has to be a separate pass _before_ populating or executing any module.
void AllocateModules(ZoneList<Declaration*>* declarations);
- // Generator code to return a fresh iterator result object. The "value"
- // property is set to a value popped from the stack, and "done" is set
- // according to the argument.
- void EmitReturnIteratorResult(bool done);
+ // Generate code to create an iterator result object. The "value" property is
+ // set to a value popped from the stack, and "done" is set according to the
+ // argument. The result object is left in the result register.
+ void EmitCreateIteratorResult(bool done);
// Try to perform a comparison as a fast inlined literal compare if
// the operands allow it. Returns true if the compare operations
@@ -437,8 +437,7 @@
// Cache cell support. This associates AST ids with global property cells
// that will be cleared during GC and collected by the type-feedback oracle.
- void RecordTypeFeedbackCell(TypeFeedbackId id,
- Handle<JSGlobalPropertyCell> cell);
+ void RecordTypeFeedbackCell(TypeFeedbackId id, Handle<Cell> cell);
// Record a call's return site offset, used to rebuild the frame if the
// called function was inlined at the site.
@@ -472,6 +471,11 @@
void EmitProfilingCounterDecrement(int delta);
void EmitProfilingCounterReset();
+ // Emit code to pop values from the stack associated with nested statements
+ // like try/catch, try/finally, etc, running the finallies and unwinding the
+ // handlers as needed.
+ void EmitUnwindBeforeReturn();
+
// Platform-specific return sequence
void EmitReturnSequence();
@@ -648,7 +652,7 @@
struct TypeFeedbackCellEntry {
TypeFeedbackId ast_id;
- Handle<JSGlobalPropertyCell> cell;
+ Handle<Cell> cell;
};
@@ -844,7 +848,7 @@
ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
int ic_total_count_;
Handle<FixedArray> handler_table_;
- Handle<JSGlobalPropertyCell> profiling_counter_;
+ Handle<Cell> profiling_counter_;
bool generate_debug_code_;
Zone* zone_;
diff --git a/src/generator.js b/src/generator.js
index cc31a44..3c8ea6f 100644
--- a/src/generator.js
+++ b/src/generator.js
@@ -55,6 +55,23 @@
return %_GeneratorThrow(this, exn);
}
+function GeneratorFunctionPrototypeConstructor(x) {
+ if (%_IsConstructCall()) {
+ throw MakeTypeError('not_constructor', ['GeneratorFunctionPrototype']);
+ }
+}
+
+function GeneratorFunctionConstructor(arg1) { // length == 1
+ var source = NewFunctionString(arguments, 'function*');
+ var global_receiver = %GlobalReceiver(global);
+ // Compile the string in the constructor and not a helper so that errors
+ // appear to come from here.
+ var f = %_CallFunction(global_receiver, %CompileString(source, true));
+ %FunctionMarkNameShouldPrintAsAnonymous(f);
+ return f;
+}
+
+
function SetUpGenerators() {
%CheckIsBootstrapping();
var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;
@@ -65,9 +82,11 @@
%SetProperty(GeneratorObjectPrototype, "constructor",
GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetPrototype(GeneratorFunctionPrototype, $Function.prototype);
+ %SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor);
%SetProperty(GeneratorFunctionPrototype, "constructor",
GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetPrototype(GeneratorFunction, $Function);
+ %SetCode(GeneratorFunction, GeneratorFunctionConstructor);
}
SetUpGenerators();
diff --git a/src/handles.cc b/src/handles.cc
index 81828d9..658bb2a 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -599,6 +599,9 @@
Handle<Object> GetScriptNameOrSourceURL(Handle<Script> script) {
Isolate* isolate = script->GetIsolate();
+ if (!isolate->IsInitialized()) {
+ return isolate->factory()->undefined_value();
+ }
Handle<String> name_or_source_url_key =
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("nameOrSourceURL"));
diff --git a/src/heap-inl.h b/src/heap-inl.h
index f0861b2..208b1ad 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -245,6 +245,8 @@
result = lo_space_->AllocateRaw(size_in_bytes, NOT_EXECUTABLE);
} else if (CELL_SPACE == space) {
result = cell_space_->AllocateRaw(size_in_bytes);
+ } else if (PROPERTY_CELL_SPACE == space) {
+ result = property_cell_space_->AllocateRaw(size_in_bytes);
} else {
ASSERT(MAP_SPACE == space);
result = map_space_->AllocateRaw(size_in_bytes);
@@ -305,7 +307,19 @@
isolate_->counters()->objs_since_last_full()->Increment();
isolate_->counters()->objs_since_last_young()->Increment();
#endif
- MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
+ MaybeObject* result = cell_space_->AllocateRaw(Cell::kSize);
+ if (result->IsFailure()) old_gen_exhausted_ = true;
+ return result;
+}
+
+
+MaybeObject* Heap::AllocateRawJSGlobalPropertyCell() {
+#ifdef DEBUG
+ isolate_->counters()->objs_since_last_full()->Increment();
+ isolate_->counters()->objs_since_last_young()->Increment();
+#endif
+ MaybeObject* result =
+ property_cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
if (result->IsFailure()) old_gen_exhausted_ = true;
return result;
}
@@ -407,7 +421,8 @@
ASSERT(type != MAP_TYPE);
ASSERT(type != CODE_TYPE);
ASSERT(type != ODDBALL_TYPE);
- ASSERT(type != JS_GLOBAL_PROPERTY_CELL_TYPE);
+ ASSERT(type != CELL_TYPE);
+ ASSERT(type != PROPERTY_CELL_TYPE);
if (type <= LAST_NAME_TYPE) {
if (type == SYMBOL_TYPE) return OLD_POINTER_SPACE;
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index b8237a6..611f6a7 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -31,6 +31,7 @@
#include "heap-profiler.h"
#include "debug.h"
+#include "types.h"
namespace v8 {
namespace internal {
@@ -888,7 +889,8 @@
#undef MAKE_STRING_MAP_CASE
default: return "system / Map";
}
- case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
+ case CELL_TYPE: return "system / Cell";
+ case PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
case FOREIGN_TYPE: return "system / Foreign";
case ODDBALL_TYPE: return "system / Oddball";
#define MAKE_STRUCT_CASE(NAME, Name, name) \
@@ -976,6 +978,9 @@
ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
} else if (obj->IsCode()) {
ExtractCodeReferences(entry, Code::cast(obj));
+ } else if (obj->IsCell()) {
+ ExtractCellReferences(entry, Cell::cast(obj));
+ extract_indexed_refs = false;
} else if (obj->IsJSGlobalPropertyCell()) {
ExtractJSGlobalPropertyCellReferences(
entry, JSGlobalPropertyCell::cast(obj));
@@ -1273,9 +1278,15 @@
}
+void V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) {
+ SetInternalReference(cell, entry, "value", cell->value());
+}
+
+
void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences(
int entry, JSGlobalPropertyCell* cell) {
SetInternalReference(cell, entry, "value", cell->value());
+ SetInternalReference(cell, entry, "type", cell->type());
}
@@ -1562,6 +1573,7 @@
&& object != heap_->empty_fixed_array()
&& object != heap_->empty_descriptor_array()
&& object != heap_->fixed_array_map()
+ && object != heap_->cell_map()
&& object != heap_->global_property_cell_map()
&& object != heap_->shared_function_info_map()
&& object != heap_->free_space_map()
@@ -2210,6 +2222,8 @@
CHECK(!debug_heap->old_pointer_space()->was_swept_conservatively());
CHECK(!debug_heap->code_space()->was_swept_conservatively());
CHECK(!debug_heap->cell_space()->was_swept_conservatively());
+ CHECK(!debug_heap->property_cell_space()->
+ was_swept_conservatively());
CHECK(!debug_heap->map_space()->was_swept_conservatively());
#endif
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index 223b240..3a91f74 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -464,6 +464,7 @@
void ExtractScriptReferences(int entry, Script* script);
void ExtractCodeCacheReferences(int entry, CodeCache* code_cache);
void ExtractCodeReferences(int entry, Code* code);
+ void ExtractCellReferences(int entry, Cell* cell);
void ExtractJSGlobalPropertyCellReferences(int entry,
JSGlobalPropertyCell* cell);
void ExtractClosureReferences(JSObject* js_obj, int entry);
diff --git a/src/heap.cc b/src/heap.cc
index 2817fcb..1df9fa1 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -105,6 +105,7 @@
code_space_(NULL),
map_space_(NULL),
cell_space_(NULL),
+ property_cell_space_(NULL),
lo_space_(NULL),
gc_state_(NOT_IN_GC),
gc_post_processing_depth_(0),
@@ -199,7 +200,8 @@
old_data_space_->Capacity() +
code_space_->Capacity() +
map_space_->Capacity() +
- cell_space_->Capacity();
+ cell_space_->Capacity() +
+ property_cell_space_->Capacity();
}
@@ -212,6 +214,7 @@
code_space_->CommittedMemory() +
map_space_->CommittedMemory() +
cell_space_->CommittedMemory() +
+ property_cell_space_->CommittedMemory() +
lo_space_->Size();
}
@@ -225,6 +228,7 @@
code_space_->CommittedPhysicalMemory() +
map_space_->CommittedPhysicalMemory() +
cell_space_->CommittedPhysicalMemory() +
+ property_cell_space_->CommittedPhysicalMemory() +
lo_space_->CommittedPhysicalMemory();
}
@@ -244,7 +248,8 @@
old_data_space_->Available() +
code_space_->Available() +
map_space_->Available() +
- cell_space_->Available();
+ cell_space_->Available() +
+ property_cell_space_->Available();
}
@@ -254,6 +259,7 @@
code_space_ != NULL &&
map_space_ != NULL &&
cell_space_ != NULL &&
+ property_cell_space_ != NULL &&
lo_space_ != NULL;
}
@@ -383,6 +389,12 @@
cell_space_->SizeOfObjects() / KB,
cell_space_->Available() / KB,
cell_space_->CommittedMemory() / KB);
+ PrintPID("PropertyCell space, used: %6" V8_PTR_PREFIX "d KB"
+ ", available: %6" V8_PTR_PREFIX "d KB"
+ ", committed: %6" V8_PTR_PREFIX "d KB\n",
+ property_cell_space_->SizeOfObjects() / KB,
+ property_cell_space_->Available() / KB,
+ property_cell_space_->CommittedMemory() / KB);
PrintPID("Large object space, used: %6" V8_PTR_PREFIX "d KB"
", available: %6" V8_PTR_PREFIX "d KB"
", committed: %6" V8_PTR_PREFIX "d KB\n",
@@ -514,6 +526,10 @@
isolate_->counters()->heap_fraction_cell_space()->AddSample(
static_cast<int>(
(cell_space()->CommittedMemory() * 100.0) / CommittedMemory()));
+ isolate_->counters()->heap_fraction_property_cell_space()->
+ AddSample(static_cast<int>(
+ (property_cell_space()->CommittedMemory() * 100.0) /
+ CommittedMemory()));
isolate_->counters()->heap_sample_total_committed()->AddSample(
static_cast<int>(CommittedMemory() / KB));
@@ -523,6 +539,10 @@
static_cast<int>(map_space()->CommittedMemory() / KB));
isolate_->counters()->heap_sample_cell_space_committed()->AddSample(
static_cast<int>(cell_space()->CommittedMemory() / KB));
+ isolate_->counters()->
+ heap_sample_property_cell_space_committed()->
+ AddSample(static_cast<int>(
+ property_cell_space()->CommittedMemory() / KB));
}
#define UPDATE_COUNTERS_FOR_SPACE(space) \
@@ -548,6 +568,7 @@
UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(code_space)
UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(map_space)
UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(cell_space)
+ UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(property_cell_space)
UPDATE_COUNTERS_AND_FRAGMENTATION_FOR_SPACE(lo_space)
#undef UPDATE_COUNTERS_FOR_SPACE
#undef UPDATE_FRAGMENTATION_FOR_SPACE
@@ -1212,7 +1233,7 @@
// Store Buffer overflowed while scanning promoted objects. These are not
// in any particular page, though they are likely to be clustered by the
// allocation routines.
- store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize);
+ store_buffer_->EnsureSpace(StoreBuffer::kStoreBufferSize / 2);
} else {
// Store Buffer overflowed while scanning a particular old space page for
// pointers to new space.
@@ -1353,15 +1374,31 @@
store_buffer()->IteratePointersToNewSpace(&ScavengeObject);
}
- // Copy objects reachable from cells by scavenging cell values directly.
+ // Copy objects reachable from simple cells by scavenging cell values
+ // directly.
HeapObjectIterator cell_iterator(cell_space_);
for (HeapObject* heap_object = cell_iterator.Next();
heap_object != NULL;
heap_object = cell_iterator.Next()) {
+ if (heap_object->IsCell()) {
+ Cell* cell = Cell::cast(heap_object);
+ Address value_address = cell->ValueAddress();
+ scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+ }
+ }
+
+ // Copy objects reachable from global property cells by scavenging global
+ // property cell values directly.
+ HeapObjectIterator js_global_property_cell_iterator(property_cell_space_);
+ for (HeapObject* heap_object = js_global_property_cell_iterator.Next();
+ heap_object != NULL;
+ heap_object = js_global_property_cell_iterator.Next()) {
if (heap_object->IsJSGlobalPropertyCell()) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(heap_object);
Address value_address = cell->ValueAddress();
scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+ Address type_address = cell->TypeAddress();
+ scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
}
}
@@ -1490,55 +1527,121 @@
}
-static Object* ProcessFunctionWeakReferences(Heap* heap,
- Object* function,
- WeakObjectRetainer* retainer,
- bool record_slots) {
+template <class T>
+struct WeakListVisitor;
+
+
+template <class T>
+static Object* VisitWeakList(Heap* heap,
+ Object* list,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
Object* undefined = heap->undefined_value();
Object* head = undefined;
- JSFunction* tail = NULL;
- Object* candidate = function;
- while (candidate != undefined) {
+ T* tail = NULL;
+ MarkCompactCollector* collector = heap->mark_compact_collector();
+ while (list != undefined) {
// Check whether to keep the candidate in the list.
- JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate);
- Object* retain = retainer->RetainAs(candidate);
- if (retain != NULL) {
+ T* candidate = reinterpret_cast<T*>(list);
+ Object* retained = retainer->RetainAs(list);
+ if (retained != NULL) {
if (head == undefined) {
// First element in the list.
- head = retain;
+ head = retained;
} else {
// Subsequent elements in the list.
ASSERT(tail != NULL);
- tail->set_next_function_link(retain);
+ WeakListVisitor<T>::SetWeakNext(tail, retained);
if (record_slots) {
- Object** next_function =
- HeapObject::RawField(tail, JSFunction::kNextFunctionLinkOffset);
- heap->mark_compact_collector()->RecordSlot(
- next_function, next_function, retain);
+ Object** next_slot =
+ HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
+ collector->RecordSlot(next_slot, next_slot, retained);
}
}
- // Retained function is new tail.
- candidate_function = reinterpret_cast<JSFunction*>(retain);
- tail = candidate_function;
+ // Retained object is new tail.
+ ASSERT(!retained->IsUndefined());
+ candidate = reinterpret_cast<T*>(retained);
+ tail = candidate;
- ASSERT(retain->IsUndefined() || retain->IsJSFunction());
- if (retain == undefined) break;
+ // tail is a live object, visit it.
+ WeakListVisitor<T>::VisitLiveObject(
+ heap, tail, retainer, record_slots);
}
// Move to next element in the list.
- candidate = candidate_function->next_function_link();
+ list = WeakListVisitor<T>::WeakNext(candidate);
}
// Terminate the list if there is one or more elements.
if (tail != NULL) {
- tail->set_next_function_link(undefined);
+ WeakListVisitor<T>::SetWeakNext(tail, undefined);
}
-
return head;
}
+template<>
+struct WeakListVisitor<JSFunction> {
+ static void SetWeakNext(JSFunction* function, Object* next) {
+ function->set_next_function_link(next);
+ }
+
+ static Object* WeakNext(JSFunction* function) {
+ return function->next_function_link();
+ }
+
+ static int WeakNextOffset() {
+ return JSFunction::kNextFunctionLinkOffset;
+ }
+
+ static void VisitLiveObject(Heap*, JSFunction*,
+ WeakObjectRetainer*, bool) {
+ }
+};
+
+
+template<>
+struct WeakListVisitor<Context> {
+ static void SetWeakNext(Context* context, Object* next) {
+ context->set(Context::NEXT_CONTEXT_LINK,
+ next,
+ UPDATE_WRITE_BARRIER);
+ }
+
+ static Object* WeakNext(Context* context) {
+ return context->get(Context::NEXT_CONTEXT_LINK);
+ }
+
+ static void VisitLiveObject(Heap* heap,
+ Context* context,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
+ // Process the weak list of optimized functions for the context.
+ Object* function_list_head =
+ VisitWeakList<JSFunction>(
+ heap,
+ context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
+ retainer,
+ record_slots);
+ context->set(Context::OPTIMIZED_FUNCTIONS_LIST,
+ function_list_head,
+ UPDATE_WRITE_BARRIER);
+ if (record_slots) {
+ Object** optimized_functions =
+ HeapObject::RawField(
+ context, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
+ heap->mark_compact_collector()->RecordSlot(
+ optimized_functions, optimized_functions, function_list_head);
+ }
+ }
+
+ static int WeakNextOffset() {
+ return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
+ }
+};
+
+
void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
// We don't record weak slots during marking or scavenges.
// Instead we do it once when we complete mark-compact cycle.
@@ -1553,168 +1656,73 @@
void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer,
bool record_slots) {
- Object* undefined = undefined_value();
- Object* head = undefined;
- Context* tail = NULL;
- Object* candidate = native_contexts_list_;
-
- while (candidate != undefined) {
- // Check whether to keep the candidate in the list.
- Context* candidate_context = reinterpret_cast<Context*>(candidate);
- Object* retain = retainer->RetainAs(candidate);
- if (retain != NULL) {
- if (head == undefined) {
- // First element in the list.
- head = retain;
- } else {
- // Subsequent elements in the list.
- ASSERT(tail != NULL);
- tail->set_unchecked(this,
- Context::NEXT_CONTEXT_LINK,
- retain,
- UPDATE_WRITE_BARRIER);
-
- if (record_slots) {
- Object** next_context =
- HeapObject::RawField(
- tail, FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK));
- mark_compact_collector()->RecordSlot(
- next_context, next_context, retain);
- }
- }
- // Retained context is new tail.
- candidate_context = reinterpret_cast<Context*>(retain);
- tail = candidate_context;
-
- if (retain == undefined) break;
-
- // Process the weak list of optimized functions for the context.
- Object* function_list_head =
- ProcessFunctionWeakReferences(
- this,
- candidate_context->get(Context::OPTIMIZED_FUNCTIONS_LIST),
- retainer,
- record_slots);
- candidate_context->set_unchecked(this,
- Context::OPTIMIZED_FUNCTIONS_LIST,
- function_list_head,
- UPDATE_WRITE_BARRIER);
- if (record_slots) {
- Object** optimized_functions =
- HeapObject::RawField(
- tail, FixedArray::SizeFor(Context::OPTIMIZED_FUNCTIONS_LIST));
- mark_compact_collector()->RecordSlot(
- optimized_functions, optimized_functions, function_list_head);
- }
- }
-
- // Move to next element in the list.
- candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK);
- }
-
- // Terminate the list if there is one or more elements.
- if (tail != NULL) {
- tail->set_unchecked(this,
- Context::NEXT_CONTEXT_LINK,
- Heap::undefined_value(),
- UPDATE_WRITE_BARRIER);
- }
-
+ Object* head =
+ VisitWeakList<Context>(
+ this, native_contexts_list(), retainer, record_slots);
// Update the head of the list of contexts.
native_contexts_list_ = head;
}
-template <class T>
-struct WeakListVisitor;
-
-
-template <class T>
-static Object* VisitWeakList(Object* list,
- MarkCompactCollector* collector,
- WeakObjectRetainer* retainer, bool record_slots) {
- Object* head = Smi::FromInt(0);
- T* tail = NULL;
- while (list != Smi::FromInt(0)) {
- Object* retained = retainer->RetainAs(list);
- if (retained != NULL) {
- if (head == Smi::FromInt(0)) {
- head = retained;
- } else {
- ASSERT(tail != NULL);
- WeakListVisitor<T>::set_weak_next(tail, retained);
- if (record_slots) {
- Object** next_slot =
- HeapObject::RawField(tail, WeakListVisitor<T>::kWeakNextOffset);
- collector->RecordSlot(next_slot, next_slot, retained);
- }
- }
- tail = reinterpret_cast<T*>(retained);
- WeakListVisitor<T>::VisitLiveObject(
- tail, collector, retainer, record_slots);
- }
- list = WeakListVisitor<T>::get_weak_next(reinterpret_cast<T*>(list));
- }
- if (tail != NULL) {
- tail->set_weak_next(Smi::FromInt(0));
- }
- return head;
-}
-
-
template<>
struct WeakListVisitor<JSTypedArray> {
- static void set_weak_next(JSTypedArray* obj, Object* next) {
+ static void SetWeakNext(JSTypedArray* obj, Object* next) {
obj->set_weak_next(next);
}
- static Object* get_weak_next(JSTypedArray* obj) {
+ static Object* WeakNext(JSTypedArray* obj) {
return obj->weak_next();
}
- static void VisitLiveObject(JSTypedArray* obj,
- MarkCompactCollector* collector,
+ static void VisitLiveObject(Heap*,
+ JSTypedArray* obj,
WeakObjectRetainer* retainer,
bool record_slots) {}
- static const int kWeakNextOffset = JSTypedArray::kWeakNextOffset;
+ static int WeakNextOffset() {
+ return JSTypedArray::kWeakNextOffset;
+ }
};
template<>
struct WeakListVisitor<JSArrayBuffer> {
- static void set_weak_next(JSArrayBuffer* obj, Object* next) {
+ static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
obj->set_weak_next(next);
}
- static Object* get_weak_next(JSArrayBuffer* obj) {
+ static Object* WeakNext(JSArrayBuffer* obj) {
return obj->weak_next();
}
- static void VisitLiveObject(JSArrayBuffer* array_buffer,
- MarkCompactCollector* collector,
+ static void VisitLiveObject(Heap* heap,
+ JSArrayBuffer* array_buffer,
WeakObjectRetainer* retainer,
bool record_slots) {
Object* typed_array_obj =
- VisitWeakList<JSTypedArray>(array_buffer->weak_first_array(),
- collector, retainer, record_slots);
+ VisitWeakList<JSTypedArray>(
+ heap,
+ array_buffer->weak_first_array(),
+ retainer, record_slots);
array_buffer->set_weak_first_array(typed_array_obj);
- if (typed_array_obj != Smi::FromInt(0) && record_slots) {
+ if (typed_array_obj != heap->undefined_value() && record_slots) {
Object** slot = HeapObject::RawField(
array_buffer, JSArrayBuffer::kWeakFirstArrayOffset);
- collector->RecordSlot(slot, slot, typed_array_obj);
+ heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
}
}
- static const int kWeakNextOffset = JSArrayBuffer::kWeakNextOffset;
+ static int WeakNextOffset() {
+ return JSArrayBuffer::kWeakNextOffset;
+ }
};
void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
bool record_slots) {
Object* array_buffer_obj =
- VisitWeakList<JSArrayBuffer>(array_buffers_list(),
- mark_compact_collector(),
+ VisitWeakList<JSArrayBuffer>(this,
+ array_buffers_list(),
retainer, record_slots);
set_array_buffers_list(array_buffer_obj);
}
@@ -2663,7 +2671,12 @@
}
set_code_map(Map::cast(obj));
- { MaybeObject* maybe_obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE,
+ { MaybeObject* maybe_obj = AllocateMap(CELL_TYPE, Cell::kSize);
+ if (!maybe_obj->ToObject(&obj)) return false;
+ }
+ set_cell_map(Map::cast(obj));
+
+ { MaybeObject* maybe_obj = AllocateMap(PROPERTY_CELL_TYPE,
JSGlobalPropertyCell::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
}
@@ -2798,14 +2811,26 @@
}
-MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
+MaybeObject* Heap::AllocateCell(Object* value) {
Object* result;
{ MaybeObject* maybe_result = AllocateRawCell();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
+ HeapObject::cast(result)->set_map_no_write_barrier(cell_map());
+ Cell::cast(result)->set_value(value);
+ return result;
+}
+
+
+MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
+ Object* result;
+ { MaybeObject* maybe_result = AllocateRawJSGlobalPropertyCell();
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
HeapObject::cast(result)->set_map_no_write_barrier(
global_property_cell_map());
JSGlobalPropertyCell::cast(result)->set_value(value);
+ JSGlobalPropertyCell::cast(result)->set_type(Type::None());
return result;
}
@@ -4469,8 +4494,7 @@
// advice
Map* initial_map = constructor->initial_map();
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
- *allocation_site_info_payload);
+ Cell* cell = Cell::cast(*allocation_site_info_payload);
Smi* smi = Smi::cast(cell->value());
ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
AllocationSiteMode mode = TRACK_ALLOCATION_SITE;
@@ -6052,6 +6076,8 @@
map_space_->ReportStatistics();
PrintF("Cell space : ");
cell_space_->ReportStatistics();
+ PrintF("JSGlobalPropertyCell space : ");
+ property_cell_space_->ReportStatistics();
PrintF("Large object space : ");
lo_space_->ReportStatistics();
PrintF(">>>>>> ========================================= >>>>>>\n");
@@ -6073,6 +6099,7 @@
code_space_->Contains(addr) ||
map_space_->Contains(addr) ||
cell_space_->Contains(addr) ||
+ property_cell_space_->Contains(addr) ||
lo_space_->SlowContains(addr));
}
@@ -6099,6 +6126,8 @@
return map_space_->Contains(addr);
case CELL_SPACE:
return cell_space_->Contains(addr);
+ case PROPERTY_CELL_SPACE:
+ return property_cell_space_->Contains(addr);
case LO_SPACE:
return lo_space_->SlowContains(addr);
}
@@ -6125,6 +6154,7 @@
old_data_space_->Verify(&no_dirty_regions_visitor);
code_space_->Verify(&no_dirty_regions_visitor);
cell_space_->Verify(&no_dirty_regions_visitor);
+ property_cell_space_->Verify(&no_dirty_regions_visitor);
lo_space_->Verify();
}
@@ -6624,6 +6654,8 @@
*stats->map_space_capacity = map_space_->Capacity();
*stats->cell_space_size = cell_space_->SizeOfObjects();
*stats->cell_space_capacity = cell_space_->Capacity();
+ *stats->property_cell_space_size = property_cell_space_->SizeOfObjects();
+ *stats->property_cell_space_capacity = property_cell_space_->Capacity();
*stats->lo_space_size = lo_space_->Size();
isolate_->global_handles()->RecordStats(stats);
*stats->memory_allocator_size = isolate()->memory_allocator()->Size();
@@ -6652,6 +6684,7 @@
+ code_space_->SizeOfObjects()
+ map_space_->SizeOfObjects()
+ cell_space_->SizeOfObjects()
+ + property_cell_space_->SizeOfObjects()
+ lo_space_->SizeOfObjects();
}
@@ -6740,11 +6773,17 @@
if (map_space_ == NULL) return false;
if (!map_space_->SetUp()) return false;
- // Initialize global property cell space.
+ // Initialize simple cell space.
cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE);
if (cell_space_ == NULL) return false;
if (!cell_space_->SetUp()) return false;
+ // Initialize global property cell space.
+ property_cell_space_ = new PropertyCellSpace(this, max_old_generation_size_,
+ PROPERTY_CELL_SPACE);
+ if (property_cell_space_ == NULL) return false;
+ if (!property_cell_space_->SetUp()) return false;
+
// The large object code space may contain code or data. We set the memory
// to be non-executable here for safety, but this means we need to enable it
// explicitly when allocating large code objects.
@@ -6785,6 +6824,7 @@
if (!CreateInitialObjects()) return false;
native_contexts_list_ = undefined_value();
+ array_buffers_list_ = undefined_value();
return true;
}
@@ -6865,6 +6905,12 @@
cell_space_ = NULL;
}
+ if (property_cell_space_ != NULL) {
+ property_cell_space_->TearDown();
+ delete property_cell_space_;
+ property_cell_space_ = NULL;
+ }
+
if (lo_space_ != NULL) {
lo_space_->TearDown();
delete lo_space_;
@@ -6955,6 +7001,8 @@
return heap_->map_space();
case CELL_SPACE:
return heap_->cell_space();
+ case PROPERTY_CELL_SPACE:
+ return heap_->property_cell_space();
case LO_SPACE:
return heap_->lo_space();
default:
@@ -6975,6 +7023,8 @@
return heap_->map_space();
case CELL_SPACE:
return heap_->cell_space();
+ case PROPERTY_CELL_SPACE:
+ return heap_->property_cell_space();
default:
return NULL;
}
@@ -7064,6 +7114,10 @@
case CELL_SPACE:
iterator_ = new HeapObjectIterator(heap_->cell_space(), size_func_);
break;
+ case PROPERTY_CELL_SPACE:
+ iterator_ = new HeapObjectIterator(heap_->property_cell_space(),
+ size_func_);
+ break;
case LO_SPACE:
iterator_ = new LargeObjectIterator(heap_->lo_space(), size_func_);
break;
diff --git a/src/heap.h b/src/heap.h
index da10efc..70d1ccb 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -60,6 +60,7 @@
V(Oddball, true_value, TrueValue) \
V(Oddball, false_value, FalseValue) \
V(Oddball, uninitialized_value, UninitializedValue) \
+ V(Map, cell_map, CellMap) \
V(Map, global_property_cell_map, GlobalPropertyCellMap) \
V(Map, shared_function_info_map, SharedFunctionInfoMap) \
V(Map, meta_map, MetaMap) \
@@ -588,6 +589,9 @@
OldSpace* code_space() { return code_space_; }
MapSpace* map_space() { return map_space_; }
CellSpace* cell_space() { return cell_space_; }
+ PropertyCellSpace* property_cell_space() {
+ return property_cell_space_;
+ }
LargeObjectSpace* lo_space() { return lo_space_; }
PagedSpace* paged_space(int idx) {
switch (idx) {
@@ -599,6 +603,8 @@
return map_space();
case CELL_SPACE:
return cell_space();
+ case PROPERTY_CELL_SPACE:
+ return property_cell_space();
case CODE_SPACE:
return code_space();
case NEW_SPACE:
@@ -933,6 +939,12 @@
// Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateSymbol();
+ // Allocate a tenured simple cell.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+ // failed.
+ // Please note this does not perform a garbage collection.
+ MUST_USE_RESULT MaybeObject* AllocateCell(Object* value);
+
// Allocate a tenured JS global property cell.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
@@ -1958,6 +1970,7 @@
OldSpace* code_space_;
MapSpace* map_space_;
CellSpace* cell_space_;
+ PropertyCellSpace* property_cell_space_;
LargeObjectSpace* lo_space_;
HeapState gc_state_;
int gc_post_processing_depth_;
@@ -2114,9 +2127,12 @@
// (since both AllocateRaw and AllocateRawMap are inlined).
MUST_USE_RESULT inline MaybeObject* AllocateRawMap();
- // Allocate an uninitialized object in the global property cell space.
+ // Allocate an uninitialized object in the simple cell space.
MUST_USE_RESULT inline MaybeObject* AllocateRawCell();
+ // Allocate an uninitialized object in the global property cell space.
+ MUST_USE_RESULT inline MaybeObject* AllocateRawJSGlobalPropertyCell();
+
// Initializes a JSObject based on its map.
void InitializeJSObjectFromMap(JSObject* obj,
FixedArray* properties,
@@ -2437,6 +2453,8 @@
int* size_per_type; // 22
int* os_error; // 23
int* end_marker; // 24
+ intptr_t* property_cell_space_size; // 25
+ intptr_t* property_cell_space_capacity; // 26
};
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 82ed261..d13a31b 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2016,6 +2016,9 @@
};
+class HArgumentsObject;
+
+
class HEnterInlined: public HTemplateInstruction<0> {
public:
HEnterInlined(Handle<JSFunction> closure,
@@ -2023,7 +2026,7 @@
FunctionLiteral* function,
InliningKind inlining_kind,
Variable* arguments_var,
- ZoneList<HValue*>* arguments_values,
+ HArgumentsObject* arguments_object,
bool undefined_receiver,
Zone* zone)
: closure_(closure),
@@ -2032,7 +2035,7 @@
function_(function),
inlining_kind_(inlining_kind),
arguments_var_(arguments_var),
- arguments_values_(arguments_values),
+ arguments_object_(arguments_object),
undefined_receiver_(undefined_receiver),
return_targets_(2, zone) {
}
@@ -2055,7 +2058,7 @@
}
Variable* arguments_var() { return arguments_var_; }
- ZoneList<HValue*>* arguments_values() { return arguments_values_; }
+ HArgumentsObject* arguments_object() { return arguments_object_; }
DECLARE_CONCRETE_INSTRUCTION(EnterInlined)
@@ -2066,7 +2069,7 @@
FunctionLiteral* function_;
InliningKind inlining_kind_;
Variable* arguments_var_;
- ZoneList<HValue*>* arguments_values_;
+ HArgumentsObject* arguments_object_;
bool undefined_receiver_;
ZoneList<HBasicBlock*> return_targets_;
};
@@ -2473,14 +2476,14 @@
class HCallNewArray: public HCallNew {
public:
HCallNewArray(HValue* context, HValue* constructor, int argument_count,
- Handle<JSGlobalPropertyCell> type_cell)
+ Handle<Cell> type_cell)
: HCallNew(context, constructor, argument_count),
type_cell_(type_cell) {
elements_kind_ = static_cast<ElementsKind>(
Smi::cast(type_cell->value())->value());
}
- Handle<JSGlobalPropertyCell> property_cell() const {
+ Handle<Cell> property_cell() const {
return type_cell_;
}
@@ -2490,7 +2493,7 @@
private:
ElementsKind elements_kind_;
- Handle<JSGlobalPropertyCell> type_cell_;
+ Handle<Cell> type_cell_;
};
@@ -2977,21 +2980,33 @@
public:
HCheckPrototypeMaps(Handle<JSObject> prototype,
Handle<JSObject> holder,
- Zone* zone)
+ Zone* zone,
+ CompilationInfo* info)
: prototypes_(2, zone),
maps_(2, zone),
first_prototype_unique_id_(),
- last_prototype_unique_id_() {
+ last_prototype_unique_id_(),
+ can_omit_prototype_maps_(true) {
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnMaps);
// Keep a list of all objects on the prototype chain up to the holder
// and the expected maps.
while (true) {
prototypes_.Add(prototype, zone);
- maps_.Add(Handle<Map>(prototype->map()), zone);
+ Handle<Map> map(prototype->map());
+ maps_.Add(map, zone);
+ can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
if (prototype.is_identical_to(holder)) break;
prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
}
+ if (can_omit_prototype_maps_) {
+ // Mark in-flight compilation as dependent on those maps.
+ for (int i = 0; i < maps()->length(); i++) {
+ Handle<Map> map = maps()->at(i);
+ map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
+ info);
+ }
+ }
}
ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
@@ -3016,12 +3031,7 @@
last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
}
- bool CanOmitPrototypeChecks() {
- for (int i = 0; i < maps()->length(); i++) {
- if (!maps()->at(i)->CanOmitPrototypeChecks()) return false;
- }
- return true;
- }
+ bool CanOmitPrototypeChecks() { return can_omit_prototype_maps_; }
protected:
virtual bool DataEquals(HValue* other) {
@@ -3035,6 +3045,7 @@
ZoneList<Handle<Map> > maps_;
UniqueValueId first_prototype_unique_id_;
UniqueValueId last_prototype_unique_id_;
+ bool can_omit_prototype_maps_;
};
@@ -3194,19 +3205,37 @@
class HArgumentsObject: public HTemplateInstruction<0> {
public:
- HArgumentsObject() {
+ HArgumentsObject(int count, Zone* zone) : values_(count, zone) {
set_representation(Representation::Tagged());
SetFlag(kIsArguments);
}
+ const ZoneList<HValue*>* arguments_values() const { return &values_; }
+ int arguments_count() const { return values_.length(); }
+
+ void AddArgument(HValue* argument, Zone* zone) {
+ values_.Add(NULL, zone); // Resize list.
+ SetOperandAt(values_.length() - 1, argument);
+ }
+
+ virtual int OperandCount() { return values_.length(); }
+ virtual HValue* OperandAt(int index) const { return values_[index]; }
+
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
DECLARE_CONCRETE_INSTRUCTION(ArgumentsObject)
+ protected:
+ virtual void InternalSetOperandAt(int index, HValue* value) {
+ values_[index] = value;
+ }
+
private:
virtual bool IsDeletable() const { return true; }
+
+ ZoneList<HValue*> values_;
};
@@ -4824,14 +4853,14 @@
class HLoadGlobalCell: public HTemplateInstruction<0> {
public:
- HLoadGlobalCell(Handle<JSGlobalPropertyCell> cell, PropertyDetails details)
+ HLoadGlobalCell(Handle<Cell> cell, PropertyDetails details)
: cell_(cell), details_(details), unique_id_() {
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnGlobalVars);
}
- Handle<JSGlobalPropertyCell> cell() const { return cell_; }
+ Handle<Cell> cell() const { return cell_; }
bool RequiresHoleCheck() const;
virtual void PrintDataTo(StringStream* stream);
@@ -4859,7 +4888,7 @@
private:
virtual bool IsDeletable() const { return !RequiresHoleCheck(); }
- Handle<JSGlobalPropertyCell> cell_;
+ Handle<Cell> cell_;
PropertyDetails details_;
UniqueValueId unique_id_;
};
@@ -5691,6 +5720,7 @@
= Representation::Tagged())
: access_(access),
field_representation_(field_representation),
+ transition_(),
transition_unique_id_(),
new_space_dominator_(NULL) {
SetOperandAt(0, obj);
@@ -5722,7 +5752,13 @@
HObjectAccess access() const { return access_; }
Handle<Map> transition() const { return transition_; }
UniqueValueId transition_unique_id() const { return transition_unique_id_; }
- void set_transition(Handle<Map> map) { transition_ = map; }
+ void SetTransition(Handle<Map> map, CompilationInfo* info) {
+ ASSERT(transition_.is_null()); // Only set once.
+ if (map->CanBeDeprecated()) {
+ map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
+ }
+ transition_ = map;
+ }
HValue* new_space_dominator() const { return new_space_dominator_; }
bool NeedsWriteBarrier() {
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index b2badcd..3d0d550 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1698,39 +1698,35 @@
void HGraphBuilder::BuildCompareNil(
HValue* value,
- CompareNilICStub::Types types,
- Handle<Map> map,
+ Handle<Type> type,
int position,
HIfContinuation* continuation) {
IfBuilder if_nil(this, position);
bool needs_or = false;
- if (types.Contains(CompareNilICStub::NULL_TYPE)) {
+ if (type->Maybe(Type::Null())) {
if (needs_or) if_nil.Or();
if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
needs_or = true;
}
- if (types.Contains(CompareNilICStub::UNDEFINED)) {
+ if (type->Maybe(Type::Undefined())) {
if (needs_or) if_nil.Or();
if_nil.If<HCompareObjectEqAndBranch>(value,
graph()->GetConstantUndefined());
needs_or = true;
}
- // Handle either undetectable or monomorphic, not both.
- ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) ||
- !types.Contains(CompareNilICStub::MONOMORPHIC_MAP));
- if (types.Contains(CompareNilICStub::UNDETECTABLE)) {
+ if (type->Maybe(Type::Undetectable())) {
if (needs_or) if_nil.Or();
if_nil.If<HIsUndetectableAndBranch>(value);
} else {
if_nil.Then();
if_nil.Else();
- if (!map.is_null() && types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
+ if (type->NumClasses() == 1) {
BuildCheckNonSmi(value);
// For ICs, the map checked below is a sentinel map that gets replaced by
// the monomorphic map when the code is used as a template to generate a
// new IC. For optimized functions, there is no sentinel map, the map
// emitted below is the actual monomorphic map.
- BuildCheckMap(value, map);
+ BuildCheckMap(value, type->Classes().Current());
} else {
if_nil.Deopt();
}
@@ -3550,6 +3546,7 @@
function_return_(NULL),
test_context_(NULL),
entry_(NULL),
+ arguments_object_(NULL),
arguments_elements_(NULL),
outer_(owner->function_state()) {
if (outer_ != NULL) {
@@ -3823,7 +3820,7 @@
void HOptimizedGraphBuilder::Bailout(const char* reason) {
- info()->set_bailout_reason(reason);
+ current_info()->set_bailout_reason(reason);
SetStackOverflow();
}
@@ -3880,11 +3877,11 @@
bool HOptimizedGraphBuilder::BuildGraph() {
- if (info()->function()->is_generator()) {
+ if (current_info()->function()->is_generator()) {
Bailout("function is a generator");
return false;
}
- Scope* scope = info()->scope();
+ Scope* scope = current_info()->scope();
if (scope->HasIllegalRedeclaration()) {
Bailout("function with illegal redeclaration");
return false;
@@ -3928,7 +3925,7 @@
AddInstruction(
new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
- VisitStatements(info()->function()->body());
+ VisitStatements(current_info()->function()->body());
if (HasStackOverflow()) return false;
if (current_block() != NULL) {
@@ -3940,7 +3937,7 @@
// last time this function was compiled, then this recompile is likely not
// due to missing/inadequate type feedback, but rather too aggressive
// optimization. Disable optimistic LICM in that case.
- Handle<Code> unoptimized_code(info()->shared_info()->code());
+ Handle<Code> unoptimized_code(current_info()->shared_info()->code());
ASSERT(unoptimized_code->kind() == Code::FUNCTION);
Handle<TypeFeedbackInfo> type_info(
TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
@@ -4701,18 +4698,18 @@
AddInstruction(undefined_constant);
graph()->set_undefined_constant(undefined_constant);
- HArgumentsObject* object = new(zone()) HArgumentsObject;
- AddInstruction(object);
- graph()->SetArgumentsObject(object);
-
- // Set the initial values of parameters including "this". "This" has
- // parameter index 0.
+ // Create an arguments object containing the initial parameters. Set the
+ // initial values of parameters including "this" having parameter index 0.
ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
-
+ HArgumentsObject* arguments_object =
+ new(zone()) HArgumentsObject(environment()->parameter_count(), zone());
for (int i = 0; i < environment()->parameter_count(); ++i) {
HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
+ arguments_object->AddArgument(parameter, zone());
environment()->Bind(i, parameter);
}
+ AddInstruction(arguments_object);
+ graph()->SetArgumentsObject(arguments_object);
// First special is HContext.
HInstruction* context = AddInstruction(new(zone()) HContext);
@@ -5027,7 +5024,7 @@
HControlInstruction* compare;
if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
- if (!clause->IsSmiCompare()) {
+ if (!clause->compare_type()->Is(Type::Integer31())) {
AddSoftDeoptimize();
}
@@ -5129,7 +5126,7 @@
bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
- return statement->OsrEntryId() == info()->osr_ast_id();
+ return statement->OsrEntryId() == current_info()->osr_ast_id();
}
@@ -5516,9 +5513,9 @@
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
Handle<SharedFunctionInfo> shared_info =
- SearchSharedFunctionInfo(info()->shared_info()->code(), expr);
+ SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr);
if (shared_info.is_null()) {
- shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
+ shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script());
}
// We also have a stack overflow if the recursive compilation did.
if (HasStackOverflow()) return;
@@ -5579,10 +5576,10 @@
HOptimizedGraphBuilder::GlobalPropertyAccess
HOptimizedGraphBuilder::LookupGlobalProperty(
Variable* var, LookupResult* lookup, bool is_store) {
- if (var->is_this() || !info()->has_global_object()) {
+ if (var->is_this() || !current_info()->has_global_object()) {
return kUseGeneric;
}
- Handle<GlobalObject> global(info()->global_object());
+ Handle<GlobalObject> global(current_info()->global_object());
global->Lookup(*var->name(), lookup);
if (!lookup->IsNormal() ||
(is_store && lookup->IsReadOnly()) ||
@@ -5597,7 +5594,7 @@
HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
ASSERT(var->IsContextSlot());
HValue* context = environment()->LookupContext();
- int length = info()->scope()->ContextChainLength(var->scope());
+ int length = current_info()->scope()->ContextChainLength(var->scope());
while (length-- > 0) {
HInstruction* context_instruction = new(zone()) HOuterContext(context);
AddInstruction(context_instruction);
@@ -5633,12 +5630,12 @@
LookupGlobalProperty(variable, &lookup, false);
if (type == kUseCell &&
- info()->global_object()->IsAccessCheckNeeded()) {
+ current_info()->global_object()->IsAccessCheckNeeded()) {
type = kUseGeneric;
}
if (type == kUseCell) {
- Handle<GlobalObject> global(info()->global_object());
+ Handle<GlobalObject> global(current_info()->global_object());
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
HLoadGlobalCell* instr =
new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
@@ -6229,7 +6226,8 @@
AddInstruction(new(zone()) HCheckPrototypeMaps(
Handle<JSObject>(JSObject::cast(map->prototype())),
Handle<JSObject>(JSObject::cast(proto)),
- zone()));
+ zone(),
+ top_info()));
}
HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
@@ -6265,7 +6263,7 @@
if (transition_to_field) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
- instr->set_transition(transition);
+ instr->SetTransition(transition, top_info());
// TODO(fschneider): Record the new map type of the object in the IR to
// enable elimination of redundant checks after the transition store.
instr->SetGVNFlag(kChangesMaps);
@@ -6568,7 +6566,7 @@
LookupResult lookup(isolate());
GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
if (type == kUseCell) {
- Handle<GlobalObject> global(info()->global_object());
+ Handle<GlobalObject> global(current_info()->global_object());
Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
HInstruction* instr =
new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
@@ -6633,13 +6631,13 @@
// Bail out if we try to mutate a parameter value in a function
// using the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
+ if (current_info()->scope()->arguments() != NULL) {
// Parameters will be allocated to context slots. We have no
// direct way to detect that the variable is a parameter so we do
// a linear search of the parameter variables.
- int count = info()->scope()->num_parameters();
+ int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
+ if (var == current_info()->scope()->parameter(i)) {
Bailout(
"assignment to parameter, function uses arguments object");
}
@@ -6859,12 +6857,12 @@
// Bail out if we try to mutate a parameter value in a function using
// the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
+ if (current_info()->scope()->arguments() != NULL) {
// Parameters will rewrite to context slots. We have no direct way
// to detect that the variable is a parameter.
- int count = info()->scope()->num_parameters();
+ int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
+ if (var == current_info()->scope()->parameter(i)) {
return Bailout("assignment to parameter in arguments object");
}
}
@@ -7026,8 +7024,8 @@
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddCheckMap(object, map);
- AddInstruction(
- new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+ AddInstruction(new(zone()) HCheckPrototypeMaps(
+ prototype, holder, zone(), top_info()));
HValue* holder_value = AddInstruction(new(zone())
HConstant(holder, Representation::Tagged()));
return BuildLoadNamedField(holder_value,
@@ -7041,7 +7039,8 @@
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddCheckMap(object, map);
- AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+ AddInstruction(new(zone()) HCheckPrototypeMaps(
+ prototype, holder, zone(), top_info()));
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
return new(zone()) HConstant(function, Representation::Tagged());
}
@@ -7078,8 +7077,8 @@
isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
- AddInstruction(
- new(zone()) HCheckPrototypeMaps(prototype, object_prototype, zone()));
+ AddInstruction(new(zone()) HCheckPrototypeMaps(
+ prototype, object_prototype, zone(), top_info()));
load_mode = ALLOW_RETURN_HOLE;
graph()->MarkDependsOnEmptyArrayProtoElements();
}
@@ -7430,7 +7429,8 @@
HEnterInlined* entry = function_state()->entry();
entry->set_arguments_pushed();
- ZoneList<HValue*>* arguments_values = entry->arguments_values();
+ HArgumentsObject* arguments = entry->arguments_object();
+ const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
HInstruction* insert_after = entry;
for (int i = 0; i < arguments_values->length(); i++) {
@@ -7594,8 +7594,8 @@
Handle<Map> receiver_map) {
if (!holder.is_null()) {
Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
- AddInstruction(
- new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
+ AddInstruction(new(zone()) HCheckPrototypeMaps(
+ prototype, holder, zone(), top_info()));
}
}
@@ -7740,7 +7740,7 @@
expr->ComputeTarget(map, name);
AddCheckPrototypeMaps(expr->holder(), map);
if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
- Handle<JSFunction> caller = info()->closure();
+ Handle<JSFunction> caller = current_info()->closure();
SmartArrayPointer<char> caller_name =
caller->shared()->DebugName()->ToCString();
PrintF("Trying to inline the polymorphic call to %s from %s\n",
@@ -7824,7 +7824,7 @@
// Precondition: call is monomorphic and we have found a target with the
// appropriate arity.
- Handle<JSFunction> caller = info()->closure();
+ Handle<JSFunction> caller = current_info()->closure();
Handle<SharedFunctionInfo> target_shared(target->shared());
// Do a quick check on source code length to avoid parsing large
@@ -7860,7 +7860,7 @@
int nodes_added = InliningAstSize(target);
if (nodes_added == kNotInlinable) return false;
- Handle<JSFunction> caller = info()->closure();
+ Handle<JSFunction> caller = current_info()->closure();
if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
TraceInline(target, caller, "target AST is too large [early]");
@@ -7869,7 +7869,7 @@
#if !defined(V8_TARGET_ARCH_IA32)
// Target must be able to use caller's context.
- CompilationInfo* outer_info = info();
+ CompilationInfo* outer_info = current_info();
if (target->context() != outer_info->closure()->context() ||
outer_info->scope()->contains_with() ||
outer_info->scope()->num_heap_slots() > 0) {
@@ -7998,7 +7998,7 @@
// Type-check the inlined function.
ASSERT(target_shared->has_deoptimization_support());
- AstTyper::Type(&target_info);
+ AstTyper::Run(&target_info);
// Save the pending call context. Set up new one for the inlined function.
// The function state is new-allocated because we need to delete it
@@ -8031,17 +8031,20 @@
AddSimulate(return_id);
current_block()->UpdateEnvironment(inner_env);
- ZoneList<HValue*>* arguments_values = NULL;
+ HArgumentsObject* arguments_object = NULL;
- // If the function uses arguments copy current arguments values
- // to use them for materialization.
+ // If the function uses arguments object create and bind one, also copy
+ // current arguments values to use them for materialization.
if (function->scope()->arguments() != NULL) {
+ ASSERT(function->scope()->arguments()->IsStackAllocated());
HEnvironment* arguments_env = inner_env->arguments_environment();
int arguments_count = arguments_env->parameter_count();
- arguments_values = new(zone()) ZoneList<HValue*>(arguments_count, zone());
+ arguments_object = new(zone()) HArgumentsObject(arguments_count, zone());
+ inner_env->Bind(function->scope()->arguments(), arguments_object);
for (int i = 0; i < arguments_count; i++) {
- arguments_values->Add(arguments_env->Lookup(i), zone());
+ arguments_object->AddArgument(arguments_env->Lookup(i), zone());
}
+ AddInstruction(arguments_object);
}
HEnterInlined* enter_inlined =
@@ -8050,20 +8053,12 @@
function,
function_state()->inlining_kind(),
function->scope()->arguments(),
- arguments_values,
+ arguments_object,
undefined_receiver,
zone());
function_state()->set_entry(enter_inlined);
AddInstruction(enter_inlined);
- // If the function uses arguments object create and bind one.
- if (function->scope()->arguments() != NULL) {
- ASSERT(function->scope()->arguments()->IsStackAllocated());
- inner_env->Bind(function->scope()->arguments(),
- graph()->GetArgumentsObject());
- }
-
-
VisitDeclarations(target_info.scope()->declarations());
VisitStatements(function->body());
if (HasStackOverflow()) {
@@ -8304,7 +8299,8 @@
Call::GetPrototypeForPrimitiveCheck(STRING_CHECK,
expr->holder()->GetIsolate()),
expr->holder(),
- zone()));
+ zone(),
+ top_info()));
HInstruction* char_code =
BuildStringCharCodeAt(context, string, index);
if (id == kStringCharCodeAt) {
@@ -8455,7 +8451,7 @@
return false;
}
- if (info()->scope()->arguments() == NULL) return false;
+ if (current_info()->scope()->arguments() == NULL) return false;
ZoneList<Expression*>* args = expr->arguments();
if (args->length() != 2) return false;
@@ -8494,13 +8490,10 @@
} else {
// We are inside inlined function and we know exactly what is inside
// arguments object. But we need to be able to materialize at deopt.
- // TODO(mstarzinger): For now we just ensure arguments are pushed
- // right after HEnterInlined, but we could be smarter about this.
- EnsureArgumentsArePushedForAccess();
ASSERT_EQ(environment()->arguments_environment()->parameter_count(),
- function_state()->entry()->arguments_values()->length());
- HEnterInlined* entry = function_state()->entry();
- ZoneList<HValue*>* arguments_values = entry->arguments_values();
+ function_state()->entry()->arguments_object()->arguments_count());
+ HArgumentsObject* args = function_state()->entry()->arguments_object();
+ const ZoneList<HValue*>* arguments_values = args->arguments_values();
int arguments_count = arguments_values->length();
PushAndAdd(new(zone()) HWrapReceiver(receiver, function));
for (int i = 1; i < arguments_count; i++) {
@@ -8696,8 +8689,8 @@
LookupResult lookup(isolate());
GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
if (type == kUseCell &&
- !info()->global_object()->IsAccessCheckNeeded()) {
- Handle<GlobalObject> global(info()->global_object());
+ !current_info()->global_object()->IsAccessCheckNeeded()) {
+ Handle<GlobalObject> global(current_info()->global_object());
known_global_function = expr->ComputeGlobalTarget(global, &lookup);
}
if (known_global_function) {
@@ -8732,7 +8725,7 @@
}
if (TryInlineCall(expr)) return;
- if (expr->target().is_identical_to(info()->closure())) {
+ if (expr->target().is_identical_to(current_info()->closure())) {
graph()->MarkRecursive();
}
@@ -8935,7 +8928,7 @@
CHECK_ALIVE(VisitArgumentList(expr->arguments()));
HCallNew* call;
if (use_call_new_array) {
- Handle<JSGlobalPropertyCell> cell = expr->allocation_info_cell();
+ Handle<Cell> cell = expr->allocation_info_cell();
call = new(zone()) HCallNewArray(context, constructor, argument_count,
cell);
} else {
@@ -9231,13 +9224,13 @@
// Bail out if we try to mutate a parameter value in a function
// using the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
- if (info()->scope()->arguments() != NULL) {
+ if (current_info()->scope()->arguments() != NULL) {
// Parameters will rewrite to context slots. We have no direct
// way to detect that the variable is a parameter so we use a
// linear search of the parameter list.
- int count = info()->scope()->num_parameters();
+ int count = current_info()->scope()->num_parameters();
for (int i = 0; i < count; ++i) {
- if (var == info()->scope()->parameter(i)) {
+ if (var == current_info()->scope()->parameter(i)) {
return Bailout("assignment to parameter in arguments object");
}
}
@@ -9688,6 +9681,7 @@
}
+// TODO(rossberg): this should die eventually.
Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
if (info.IsUninitialized()) return Representation::None();
if (info.IsSmi()) return Representation::Integer32();
@@ -9698,6 +9692,14 @@
}
+Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
+ if (type->Is(Type::None())) return Representation::None();
+ if (type->Is(Type::Integer32())) return Representation::Integer32();
+ if (type->Is(Type::Number())) return Representation::Double();
+ return Representation::Tagged();
+}
+
+
void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
HTypeof* typeof_expr,
Handle<String> check) {
@@ -9787,17 +9789,17 @@
return ast_context()->ReturnControl(instr, expr->id());
}
- TypeInfo left_type = expr->left_type();
- TypeInfo right_type = expr->right_type();
- TypeInfo overall_type = expr->overall_type();
+ Handle<Type> left_type = expr->left_type();
+ Handle<Type> right_type = expr->right_type();
+ Handle<Type> overall_type = expr->overall_type();
Representation combined_rep = ToRepresentation(overall_type);
Representation left_rep = ToRepresentation(left_type);
Representation right_rep = ToRepresentation(right_type);
// Check if this expression was ever executed according to type feedback.
// Note that for the special typeof/null/undefined cases we get unknown here.
- if (overall_type.IsUninitialized()) {
+ if (overall_type->Is(Type::None())) {
AddSoftDeoptimize();
- overall_type = left_type = right_type = TypeInfo::Unknown();
+ overall_type = left_type = right_type = handle(Type::Any(), isolate());
}
CHECK_ALIVE(VisitForValue(expr->left()));
@@ -9836,10 +9838,10 @@
VariableProxy* proxy = expr->right()->AsVariableProxy();
bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
if (global_function &&
- info()->has_global_object() &&
- !info()->global_object()->IsAccessCheckNeeded()) {
+ current_info()->has_global_object() &&
+ !current_info()->global_object()->IsAccessCheckNeeded()) {
Handle<String> name = proxy->name();
- Handle<GlobalObject> global(info()->global_object());
+ Handle<GlobalObject> global(current_info()->global_object());
LookupResult lookup(isolate());
global->Lookup(*name, &lookup);
if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) {
@@ -9869,13 +9871,13 @@
HIn* result = new(zone()) HIn(context, left, right);
result->set_position(expr->position());
return ast_context()->ReturnInstruction(result, expr->id());
- } else if (overall_type.IsNonPrimitive()) {
+ } else if (overall_type->Is(Type::Receiver())) {
switch (op) {
case Token::EQ:
case Token::EQ_STRICT: {
// Can we get away with map check and not instance type check?
- Handle<Map> map = expr->map();
- if (!map.is_null()) {
+ if (overall_type->IsClass()) {
+ Handle<Map> map = overall_type->AsClass();
AddCheckMapsWithTransitions(left, map);
AddCheckMapsWithTransitions(right, map);
HCompareObjectEqAndBranch* result =
@@ -9896,7 +9898,7 @@
default:
return Bailout("Unsupported non-primitive compare");
}
- } else if (overall_type.IsInternalizedString() &&
+ } else if (overall_type->Is(Type::InternalizedString()) &&
Token::IsEqualityOp(op)) {
BuildCheckNonSmi(left);
AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
@@ -9931,8 +9933,8 @@
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
+ ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
HIfContinuation continuation;
- CompareNilICStub::Types types;
if (expr->op() == Token::EQ_STRICT) {
IfBuilder if_nil(this);
if_nil.If<HCompareObjectEqAndBranch>(
@@ -9943,11 +9945,9 @@
if_nil.CaptureContinuation(&continuation);
return ast_context()->ReturnContinuation(&continuation, expr->id());
}
- types = CompareNilICStub::Types(expr->compare_nil_types());
- if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare();
- Handle<Map> map_handle = expr->map();
- BuildCompareNil(value, types, map_handle,
- expr->position(), &continuation);
+ Handle<Type> type = expr->compare_nil_type()->Is(Type::None())
+ ? handle(Type::Any(), isolate_) : expr->compare_nil_type();
+ BuildCompareNil(value, type, expr->position(), &continuation);
return ast_context()->ReturnContinuation(&continuation, expr->id());
}
@@ -10282,9 +10282,9 @@
Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
- int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
- DeclareGlobalsNativeFlag::encode(info()->is_native()) |
- DeclareGlobalsLanguageMode::encode(info()->language_mode());
+ int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
+ DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
+ DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
HInstruction* result = new(zone()) HDeclareGlobals(
environment()->LookupContext(), array, flags);
AddInstruction(result);
@@ -10338,8 +10338,8 @@
switch (variable->location()) {
case Variable::UNALLOCATED: {
globals_.Add(variable->name(), zone());
- Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(declaration->fun(), info()->script());
+ Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
+ declaration->fun(), current_info()->script());
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_.Add(function, zone());
@@ -11005,6 +11005,7 @@
values_(arguments, zone),
frame_type_(frame_type),
parameter_count_(arguments),
+ specials_count_(0),
local_count_(0),
outer_(outer),
entry_(NULL),
diff --git a/src/hydrogen.h b/src/hydrogen.h
index ad89e50..3680775 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -260,6 +260,7 @@
HStackCheck* stack_check_;
};
+
class BoundsCheckTable;
class HGraph: public ZoneObject {
public:
@@ -402,6 +403,12 @@
}
void MarkDependsOnEmptyArrayProtoElements() {
+ // Add map dependency if not already added.
+ if (depends_on_empty_array_proto_elements_) return;
+ isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo(
+ DependentCode::kElementsCantBeAddedGroup, info());
+ isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo(
+ DependentCode::kElementsCantBeAddedGroup, info());
depends_on_empty_array_proto_elements_ = true;
}
@@ -874,6 +881,11 @@
HEnterInlined* entry() { return entry_; }
void set_entry(HEnterInlined* entry) { entry_ = entry; }
+ HArgumentsObject* arguments_object() { return arguments_object_; }
+ void set_arguments_object(HArgumentsObject* arguments_object) {
+ arguments_object_ = arguments_object;
+ }
+
HArgumentsElements* arguments_elements() { return arguments_elements_; }
void set_arguments_elements(HArgumentsElements* arguments_elements) {
arguments_elements_ = arguments_elements;
@@ -907,6 +919,7 @@
// entry.
HEnterInlined* entry_;
+ HArgumentsObject* arguments_object_;
HArgumentsElements* arguments_elements_;
FunctionState* outer_;
@@ -968,6 +981,7 @@
Zone* zone() const { return info_->zone(); }
HGraph* graph() const { return graph_; }
Isolate* isolate() const { return graph_->isolate(); }
+ CompilationInfo* top_info() { return info_; }
HGraph* CreateGraph();
@@ -1350,8 +1364,7 @@
void BuildCompareNil(
HValue* value,
- CompareNilICStub::Types types,
- Handle<Map> map,
+ Handle<Type> type,
int position,
HIfContinuation* continuation);
@@ -1488,7 +1501,7 @@
void set_ast_context(AstContext* context) { ast_context_ = context; }
// Accessors forwarded to the function state.
- CompilationInfo* info() const {
+ CompilationInfo* current_info() const {
return function_state()->compilation_info();
}
AstContext* call_context() const {
@@ -1622,6 +1635,7 @@
template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
static Representation ToRepresentation(TypeInfo info);
+ static Representation ToRepresentation(Handle<Type> type);
void SetUpScope(Scope* scope);
virtual void VisitStatements(ZoneList<Statement*>* statements);
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index 2a0c920..0c737ac 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -162,24 +162,22 @@
}
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+ ASSERT(rmode_ == RelocInfo::CELL);
Address address = Memory::Address_at(pc_);
- return Handle<JSGlobalPropertyCell>(
- reinterpret_cast<JSGlobalPropertyCell**>(address));
+ return Handle<Cell>(reinterpret_cast<Cell**>(address));
}
-JSGlobalPropertyCell* RelocInfo::target_cell() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ return Cell::FromValueAddress(Memory::Address_at(pc_));
}
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
- WriteBarrierMode mode) {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
CPU::FlushICache(pc_, sizeof(Address));
if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
@@ -259,8 +257,8 @@
CPU::FlushICache(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
visitor->VisitCodeTarget(this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- visitor->VisitGlobalPropertyCell(this);
+ } else if (mode == RelocInfo::CELL) {
+ visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
CPU::FlushICache(pc_, sizeof(Address));
@@ -289,8 +287,8 @@
CPU::FlushICache(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(heap, this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- StaticVisitor::VisitGlobalPropertyCell(heap, this);
+ } else if (mode == RelocInfo::CELL) {
+ StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
CPU::FlushICache(pc_, sizeof(Address));
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 5d11452..353f265 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -410,10 +410,10 @@
RelocInfo::EXTERNAL_REFERENCE);
}
- static Operand Cell(Handle<JSGlobalPropertyCell> cell) {
+ static Operand ForCell(Handle<Cell> cell) {
AllowDeferredHandleDereference embedding_raw_address;
return Operand(reinterpret_cast<int32_t>(cell.location()),
- RelocInfo::GLOBAL_PROPERTY_CELL);
+ RelocInfo::CELL);
}
// Returns true if this Operand is a wrapper for the specified register.
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index ad1c65d..aa4b8a2 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4703,13 +4703,13 @@
__ j(equal, &initialize, Label::kNear);
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
__ jmp(&done, Label::kNear);
// An uninitialized cache is patched with the function.
__ bind(&initialize);
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
+ __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -4727,7 +4727,7 @@
Label initialize, done, miss, megamorphic, not_array_function;
// Load the cache state into ecx.
- __ mov(ecx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
+ __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset));
// A monomorphic cache hit or an already megamorphic state: invoke the
// function without changing the state.
@@ -4762,7 +4762,7 @@
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
__ bind(&megamorphic);
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
__ jmp(&done, Label::kNear);
@@ -4781,12 +4781,12 @@
Handle<Object> initial_kind_sentinel =
TypeFeedbackCells::MonomorphicArraySentinel(isolate,
GetInitialFastElementsKind());
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(initial_kind_sentinel));
__ jmp(&done);
__ bind(¬_array_function);
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
+ __ mov(FieldOperand(ebx, Cell::kValueOffset), edi);
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -4857,7 +4857,7 @@
// If there is a call target cache, mark it megamorphic in the
// non-function case. MegamorphicSentinel is an immortal immovable
// object (undefined) so no write barrier is needed.
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate)));
}
// Check for function proxy.
@@ -7930,13 +7930,12 @@
__ CmpObjectType(ecx, MAP_TYPE, ecx);
__ Assert(equal, "Unexpected initial map for Array function");
- // We should either have undefined in ebx or a valid jsglobalpropertycell
+ // We should either have undefined in ebx or a valid cell
Label okay_here;
- Handle<Map> global_property_cell_map(
- masm->isolate()->heap()->global_property_cell_map());
+ Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
__ cmp(ebx, Immediate(undefined_sentinel));
__ j(equal, &okay_here);
- __ cmp(FieldOperand(ebx, 0), Immediate(global_property_cell_map));
+ __ cmp(FieldOperand(ebx, 0), Immediate(cell_map));
__ Assert(equal, "Expected property cell in register ebx");
__ bind(&okay_here);
}
@@ -7946,7 +7945,7 @@
// Get the elements kind and case on that.
__ cmp(ebx, Immediate(undefined_sentinel));
__ j(equal, &no_info);
- __ mov(edx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
+ __ mov(edx, FieldOperand(ebx, Cell::kValueOffset));
__ JumpIfNotSmi(edx, &no_info);
__ SmiUntag(edx);
__ jmp(&switch_ready);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index c77faaa..8b01a8b 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -118,7 +118,7 @@
CompilationInfo* info = info_;
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
- profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+ profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -315,7 +315,7 @@
void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
__ mov(ebx, Immediate(profiling_counter_));
- __ sub(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ sub(FieldOperand(ebx, Cell::kValueOffset),
Immediate(Smi::FromInt(delta)));
}
@@ -327,7 +327,7 @@
reset_value = Smi::kMaxValue;
}
__ mov(ebx, Immediate(profiling_counter_));
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(Smi::FromInt(reset_value)));
}
@@ -1105,14 +1105,12 @@
Label non_proxy;
__ bind(&fixed_array);
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(
- Handle<Object>(
- Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
- isolate()));
+ Handle<Cell> cell = isolate()->factory()->NewCell(
+ Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+ isolate()));
RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
__ LoadHeapObject(ebx, cell);
- __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
+ __ mov(FieldOperand(ebx, Cell::kValueOffset),
Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
@@ -1950,8 +1948,12 @@
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::INITIAL:
- case Yield::SUSPEND: {
+ case Yield::SUSPEND:
+ // Pop value from top-of-stack slot; box result into result register.
+ EmitCreateIteratorResult(false);
+ __ push(result_register());
+ // Fall through.
+ case Yield::INITIAL: {
VisitForStackValue(expr->generator_object());
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ mov(context_register(),
@@ -1960,12 +1962,8 @@
Label resume;
__ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
__ j(not_equal, &resume);
- if (expr->yield_kind() == Yield::SUSPEND) {
- EmitReturnIteratorResult(false);
- } else {
- __ pop(result_register());
- EmitReturnSequence();
- }
+ __ pop(result_register());
+ EmitReturnSequence();
__ bind(&resume);
context()->Plug(result_register());
@@ -1977,7 +1975,10 @@
__ mov(FieldOperand(result_register(),
JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
- EmitReturnIteratorResult(true);
+ // Pop value from top-of-stack slot, box result into result register.
+ EmitCreateIteratorResult(true);
+ EmitUnwindBeforeReturn();
+ EmitReturnSequence();
break;
}
@@ -2006,17 +2007,18 @@
// try { received = yield result.value }
__ bind(&l_try);
- __ pop(eax); // result.value
+ EmitCreateIteratorResult(false); // pop and box to eax
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(eax); // result.value
+ __ push(eax); // result
__ push(Operand(esp, (0 + 1) * kPointerSize + handler_size)); // g
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ CompareRoot(eax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &l_resume);
- EmitReturnIteratorResult(false);
+ __ pop(eax); // result
+ EmitReturnSequence();
__ bind(&l_resume); // received in eax
__ PopTryHandler();
@@ -2169,13 +2171,20 @@
}
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Label gc_required;
Label allocated;
Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
+ __ jmp(&allocated);
+
+ __ bind(&gc_required);
+ __ Push(Smi::FromInt(map->instance_size()));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ __ mov(context_register(),
+ Operand(ebp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ mov(ebx, map);
@@ -2194,26 +2203,6 @@
// root set.
__ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
ecx, edx, kDontSaveFPRegs);
-
- if (done) {
- // Exit all nested statements.
- NestedStatement* current = nesting_stack_;
- int stack_depth = 0;
- int context_length = 0;
- while (current != NULL) {
- current = current->Exit(&stack_depth, &context_length);
- }
- __ Drop(stack_depth);
- }
-
- EmitReturnSequence();
-
- __ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
- __ mov(context_register(),
- Operand(ebp, StandardFrameConstants::kContextOffset));
- __ jmp(&allocated);
}
@@ -2637,8 +2626,7 @@
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
__ mov(ebx, cell);
@@ -2822,8 +2810,7 @@
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
__ mov(ebx, cell);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 7d685bf..cfda00a 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -109,20 +109,7 @@
if (!info()->IsStub()) {
Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}
- for (int i = 0 ; i < prototype_maps_.length(); i++) {
- prototype_maps_.at(i)->AddDependentCode(
- DependentCode::kPrototypeCheckGroup, code);
- }
- for (int i = 0 ; i < transition_maps_.length(); i++) {
- transition_maps_.at(i)->AddDependentCode(
- DependentCode::kTransitionGroup, code);
- }
- if (graph()->depends_on_empty_array_proto_elements()) {
- isolate()->initial_object_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- isolate()->initial_array_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- }
+ info()->CommitDependentMaps(code);
}
@@ -627,27 +614,15 @@
void LCodeGen::WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* pushed_arguments_index,
- int* pushed_arguments_count) {
+ Translation* translation) {
if (environment == NULL) return;
// The translation includes one command per value in the environment.
- int translation_size = environment->values()->length();
+ int translation_size = environment->translation_size();
// The output frame height does not include the parameters.
int height = translation_size - environment->parameter_count();
- // Function parameters are arguments to the outermost environment. The
- // arguments index points to the first element of a sequence of tagged
- // values on the stack that represent the arguments. This needs to be
- // kept in sync with the LArgumentsElements implementation.
- *pushed_arguments_index = -environment->parameter_count();
- *pushed_arguments_count = environment->parameter_count();
-
- WriteTranslation(environment->outer(),
- translation,
- pushed_arguments_index,
- pushed_arguments_count);
+ WriteTranslation(environment->outer(), translation);
bool has_closure_id = !info()->closure().is_null() &&
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
@@ -680,23 +655,6 @@
UNREACHABLE();
}
- // Inlined frames which push their arguments cause the index to be
- // bumped and another stack area to be used for materialization,
- // otherwise actual argument values are unknown for inlined frames.
- bool arguments_known = true;
- int arguments_index = *pushed_arguments_index;
- int arguments_count = *pushed_arguments_count;
- if (environment->entry() != NULL) {
- arguments_known = environment->entry()->arguments_pushed();
- arguments_index = arguments_index < 0
- ? GetStackSlotCount() : arguments_index + arguments_count;
- arguments_count = environment->entry()->arguments_count() + 1;
- if (environment->entry()->arguments_pushed()) {
- *pushed_arguments_index = arguments_index;
- *pushed_arguments_count = arguments_count;
- }
- }
-
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either
@@ -708,10 +666,7 @@
AddToTranslation(translation,
environment->spilled_registers()[value->index()],
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
} else if (
value->IsDoubleRegister() &&
environment->spilled_double_registers()[value->index()] != NULL) {
@@ -720,20 +675,36 @@
translation,
environment->spilled_double_registers()[value->index()],
false,
- false,
- arguments_known,
- arguments_index,
- arguments_count);
+ false);
}
}
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsRegister() ||
+ environment->spilled_registers()[value->index()] == NULL);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsDoubleRegister() ||
+ environment->spilled_double_registers()[value->index()] == NULL);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
}
}
@@ -741,17 +712,8 @@
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count) {
- if (op == NULL) {
- // TODO(twuerthinger): Introduce marker operands to indicate that this value
- // is not present and must be reconstructed from the deoptimizer. Currently
- // this is only used for the arguments object.
- translation->StoreArgumentsObject(
- arguments_known, arguments_index, arguments_count);
- } else if (op->IsStackSlot()) {
+ bool is_uint32) {
+ if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
} else if (is_uint32) {
@@ -877,8 +839,6 @@
int frame_count = 0;
int jsframe_count = 0;
- int args_index = 0;
- int args_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
if (e->frame_type() == JS_FUNCTION) {
@@ -886,7 +846,7 @@
}
}
Translation translation(&translations_, frame_count, jsframe_count, zone());
- WriteTranslation(environment, &translation, &args_index, &args_count);
+ WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset();
environment->Register(deoptimization_index,
@@ -2719,9 +2679,8 @@
Register map = ToRegister(instr->temp());
__ mov(map, FieldOperand(object, HeapObject::kMapOffset));
__ bind(deferred->map_check()); // Label for calculating code patching.
- Handle<JSGlobalPropertyCell> cache_cell =
- factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
- __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map.
+ Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
+ __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map.
__ j(not_equal, &cache_miss, Label::kNear);
__ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
__ jmp(&done);
@@ -2903,7 +2862,7 @@
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
Register result = ToRegister(instr->result());
- __ mov(result, Operand::Cell(instr->hydrogen()->cell()));
+ __ mov(result, Operand::ForCell(instr->hydrogen()->cell()));
if (instr->hydrogen()->RequiresHoleCheck()) {
__ cmp(result, factory()->the_hole_value());
DeoptimizeIf(equal, instr->environment());
@@ -2933,12 +2892,12 @@
// to update the property details in the property dictionary to mark
// it as no longer deleted. We deoptimize in that case.
if (instr->hydrogen()->RequiresHoleCheck()) {
- __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value());
+ __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
DeoptimizeIf(equal, instr->environment());
}
// Store the value.
- __ mov(Operand::Cell(cell_handle), value);
+ __ mov(Operand::ForCell(cell_handle), value);
// Cells are always rescanned, so no write barrier here.
}
@@ -4266,8 +4225,26 @@
ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else if (instr->arity() == 1) {
+ Label done;
+ if (IsFastPackedElementsKind(kind)) {
+ Label packed_case;
+ // We might need a change here
+ // look at the first argument
+ __ mov(ecx, Operand(esp, 0));
+ __ test(ecx, ecx);
+ __ j(zero, &packed_case);
+
+ ElementsKind holey_kind = GetHoleyElementsKind(kind);
+ ArraySingleArgumentConstructorStub stub(holey_kind,
+ disable_allocation_sites);
+ CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ jmp(&done);
+ __ bind(&packed_case);
+ }
+
ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ bind(&done);
} else {
ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4331,9 +4308,6 @@
}
if (!transition.is_null()) {
- if (transition->CanBeDeprecated()) {
- transition_maps_.Add(transition, info()->zone());
- }
if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
__ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
} else {
@@ -5790,9 +5764,8 @@
Handle<JSFunction> target = instr->hydrogen()->target();
if (instr->hydrogen()->target_in_new_space()) {
Register reg = ToRegister(instr->value());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(target);
- __ cmp(reg, Operand::Cell(cell));
+ Handle<Cell> cell = isolate()->factory()->NewCell(target);
+ __ cmp(reg, Operand::ForCell(cell));
} else {
Operand operand = ToOperand(instr->value());
__ cmp(operand, target);
@@ -6009,11 +5982,7 @@
ASSERT(prototypes->length() == maps->length());
- if (instr->hydrogen()->CanOmitPrototypeChecks()) {
- for (int i = 0; i < maps->length(); i++) {
- prototype_maps_.Add(maps->at(i), info()->zone());
- }
- } else {
+ if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
for (int i = 0; i < prototypes->length(); i++) {
__ LoadHeapObject(reg, prototypes->at(i));
DoCheckMapCommon(reg, maps->at(i), instr);
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 647dd0e..21f6076 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -58,8 +58,6 @@
deoptimizations_(4, info->zone()),
jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
- prototype_maps_(0, info->zone()),
- transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -170,10 +168,7 @@
void DoGap(LGap* instr);
// Emit frame translation commands for an environment.
- void WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* arguments_index,
- int* arguments_count);
+ void WriteTranslation(LEnvironment* environment, Translation* translation);
void EnsureRelocSpaceForDeoptimization();
@@ -287,10 +282,7 @@
void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -409,8 +401,6 @@
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
- ZoneList<Handle<Map> > prototype_maps_;
- ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 325ed2c..216872d 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -990,7 +990,7 @@
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
- int value_count = hydrogen_env->length();
+ int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
LEnvironment* result =
new(zone()) LEnvironment(hydrogen_env->closure(),
hydrogen_env->frame_type(),
@@ -1001,13 +1001,15 @@
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- for (int i = 0; i < value_count; ++i) {
+ for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
HValue* value = hydrogen_env->values()->at(i);
LOperand* op = NULL;
if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
@@ -1019,6 +1021,22 @@
value->CheckFlag(HInstruction::kUint32));
}
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ ASSERT(HInstruction::cast(value)->IsLinked());
+ LOperand* op = UseAny(value);
+ result->AddValue(op,
+ value->representation(),
+ value->CheckFlag(HInstruction::kUint32));
+ }
+ }
+
if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 38b02a5..60c5c26 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -2495,9 +2495,8 @@
Handle<HeapObject> object) {
AllowDeferredHandleDereference embedding_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- mov(result, Operand::Cell(cell));
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ mov(result, Operand::ForCell(cell));
} else {
mov(result, object);
}
@@ -2507,9 +2506,8 @@
void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- cmp(reg, Operand::Cell(cell));
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ cmp(reg, Operand::ForCell(cell));
} else {
cmp(reg, object);
}
@@ -2519,9 +2517,8 @@
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- push(Operand::Cell(cell));
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ push(Operand::ForCell(cell));
} else {
Push(object);
}
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 3906623..93923a7 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -762,7 +762,7 @@
__ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
Immediate(the_hole));
} else {
- __ cmp(Operand::Cell(cell), Immediate(the_hole));
+ __ cmp(Operand::ForCell(cell), Immediate(the_hole));
}
__ j(not_equal, miss);
}
@@ -1565,15 +1565,15 @@
void CallStubCompiler::GenerateLoadFunctionFromCell(
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Label* miss) {
// Get the value from the cell.
if (Serializer::enabled()) {
__ mov(edi, Immediate(cell));
- __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
+ __ mov(edi, FieldOperand(edi, Cell::kValueOffset));
} else {
- __ mov(edi, Operand::Cell(cell));
+ __ mov(edi, Operand::ForCell(cell));
}
// Check that the cell contains the same function.
@@ -1667,7 +1667,7 @@
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1925,7 +1925,7 @@
Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2007,7 +2007,7 @@
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2091,7 +2091,7 @@
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2177,7 +2177,7 @@
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2253,7 +2253,7 @@
Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2384,7 +2384,7 @@
Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2491,7 +2491,7 @@
const CallOptimization& optimization,
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
ASSERT(optimization.is_simple_api_call());
@@ -2673,7 +2673,7 @@
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
- Handle<JSGlobalPropertyCell>::null(),
+ Handle<Cell>::null(),
function, Handle<String>::cast(name));
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
@@ -3121,7 +3121,7 @@
__ mov(eax, Immediate(cell));
__ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset));
} else {
- __ mov(eax, Operand::Cell(cell));
+ __ mov(eax, Operand::ForCell(cell));
}
// Check for deleted property if property can actually be deleted.
diff --git a/src/ic.cc b/src/ic.cc
index 94e8773..095b614 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -2420,8 +2420,8 @@
}
UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
- ::v8::internal::TypeInfo operand_type =
- ::v8::internal::TypeInfo::TypeFromValue(operand);
+ v8::internal::TypeInfo operand_type =
+ v8::internal::TypeInfo::FromValue(operand);
if (operand_type.IsSmi()) {
return SMI;
} else if (operand_type.IsNumber()) {
@@ -2545,8 +2545,7 @@
static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
Token::Value op) {
- ::v8::internal::TypeInfo type =
- ::v8::internal::TypeInfo::TypeFromValue(value);
+ v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
if (type.IsSmi()) return BinaryOpIC::SMI;
if (type.IsInteger32()) {
if (kSmiValueSize == 32) return BinaryOpIC::SMI;
@@ -2767,10 +2766,39 @@
case OBJECT: return "OBJECT";
case KNOWN_OBJECT: return "KNOWN_OBJECT";
case GENERIC: return "GENERIC";
- default:
- UNREACHABLE();
- return NULL;
}
+ UNREACHABLE();
+ return NULL;
+}
+
+
+Handle<Type> CompareIC::StateToType(
+ Isolate* isolate,
+ CompareIC::State state,
+ Handle<Map> map) {
+ switch (state) {
+ case CompareIC::UNINITIALIZED:
+ return handle(Type::None(), isolate);
+ case CompareIC::SMI:
+ return handle(Type::Integer31(), isolate);
+ case CompareIC::NUMBER:
+ return handle(Type::Number(), isolate);
+ case CompareIC::STRING:
+ return handle(Type::String(), isolate);
+ case CompareIC::INTERNALIZED_STRING:
+ return handle(Type::InternalizedString(), isolate);
+ case CompareIC::UNIQUE_NAME:
+ return handle(Type::UniqueName(), isolate);
+ case CompareIC::OBJECT:
+ return handle(Type::Receiver(), isolate);
+ case CompareIC::KNOWN_OBJECT:
+ return handle(
+ map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
+ case CompareIC::GENERIC:
+ return handle(Type::Any(), isolate);
+ }
+ UNREACHABLE();
+ return Handle<Type>();
}
@@ -2934,7 +2962,7 @@
Code::ExtraICState state = target->extended_extra_ic_state();
CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
- stub.ClearTypes();
+ stub.ClearState();
Code* code = NULL;
CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
@@ -2961,9 +2989,9 @@
// types must be supported as a result of the miss.
bool already_monomorphic = stub.IsMonomorphic();
- CompareNilICStub::Types old_types = stub.GetTypes();
+ CompareNilICStub::State old_state = stub.GetState();
stub.Record(object);
- old_types.TraceTransition(stub.GetTypes());
+ old_state.TraceTransition(stub.GetState());
NilValue nil = stub.GetNilValue();
diff --git a/src/ic.h b/src/ic.h
index 8c448eb..fc869ad 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -741,6 +741,9 @@
GENERIC
};
+ static Handle<Type> StateToType(
+ Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
+
CompareIC(Isolate* isolate, Token::Value op)
: IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index e19d6e2..80dc8ea 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -394,6 +394,7 @@
chunk->SetFlag(MemoryChunk::RESCAN_ON_EVACUATION);
}
} else if (chunk->owner()->identity() == CELL_SPACE ||
+ chunk->owner()->identity() == PROPERTY_CELL_SPACE ||
chunk->scan_on_scavenge()) {
chunk->ClearFlag(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING);
chunk->ClearFlag(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
@@ -440,6 +441,7 @@
DeactivateIncrementalWriteBarrierForSpace(heap_->old_pointer_space());
DeactivateIncrementalWriteBarrierForSpace(heap_->old_data_space());
DeactivateIncrementalWriteBarrierForSpace(heap_->cell_space());
+ DeactivateIncrementalWriteBarrierForSpace(heap_->property_cell_space());
DeactivateIncrementalWriteBarrierForSpace(heap_->map_space());
DeactivateIncrementalWriteBarrierForSpace(heap_->code_space());
DeactivateIncrementalWriteBarrierForSpace(heap_->new_space());
@@ -474,6 +476,7 @@
ActivateIncrementalWriteBarrier(heap_->old_pointer_space());
ActivateIncrementalWriteBarrier(heap_->old_data_space());
ActivateIncrementalWriteBarrier(heap_->cell_space());
+ ActivateIncrementalWriteBarrier(heap_->property_cell_space());
ActivateIncrementalWriteBarrier(heap_->map_space());
ActivateIncrementalWriteBarrier(heap_->code_space());
ActivateIncrementalWriteBarrier(heap_->new_space());
diff --git a/src/isolate.cc b/src/isolate.cc
index 7cce14a..6c797b2 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -2007,6 +2007,9 @@
delete external_reference_table_;
external_reference_table_ = NULL;
+ delete callback_table_;
+ callback_table_ = NULL;
+
#ifdef ENABLE_DEBUGGER_SUPPORT
delete debugger_;
debugger_ = NULL;
diff --git a/src/lithium.h b/src/lithium.h
index 170e5c8..ab34453 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -527,6 +527,7 @@
deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
translation_index_(-1),
ast_id_(ast_id),
+ translation_size_(value_count),
parameter_count_(parameter_count),
pc_offset_(-1),
values_(value_count, zone),
@@ -544,6 +545,7 @@
int deoptimization_index() const { return deoptimization_index_; }
int translation_index() const { return translation_index_; }
BailoutId ast_id() const { return ast_id_; }
+ int translation_size() const { return translation_size_; }
int parameter_count() const { return parameter_count_; }
int pc_offset() const { return pc_offset_; }
LOperand** spilled_registers() const { return spilled_registers_; }
@@ -553,6 +555,7 @@
const ZoneList<LOperand*>* values() const { return &values_; }
LEnvironment* outer() const { return outer_; }
HEnterInlined* entry() { return entry_; }
+ Zone* zone() const { return zone_; }
void AddValue(LOperand* operand,
Representation representation,
@@ -560,11 +563,11 @@
values_.Add(operand, zone());
if (representation.IsSmiOrTagged()) {
ASSERT(!is_uint32);
- is_tagged_.Add(values_.length() - 1);
+ is_tagged_.Add(values_.length() - 1, zone());
}
if (is_uint32) {
- is_uint32_.Add(values_.length() - 1);
+ is_uint32_.Add(values_.length() - 1, zone());
}
}
@@ -596,8 +599,6 @@
void PrintTo(StringStream* stream);
- Zone* zone() const { return zone_; }
-
private:
Handle<JSFunction> closure_;
FrameType frame_type_;
@@ -605,11 +606,15 @@
int deoptimization_index_;
int translation_index_;
BailoutId ast_id_;
+ int translation_size_;
int parameter_count_;
int pc_offset_;
+
+ // Value array: [parameters] [locals] [expression stack] [de-materialized].
+ // |>--------- translation_size ---------<|
ZoneList<LOperand*> values_;
- BitVector is_tagged_;
- BitVector is_uint32_;
+ GrowableBitVector is_tagged_;
+ GrowableBitVector is_uint32_;
// Allocation index indexed arrays of spill slot operands for registers
// that are also in spill slots at an OSR entry. NULL for environments
@@ -619,7 +624,6 @@
LEnvironment* outer_;
HEnterInlined* entry_;
-
Zone* zone_;
};
diff --git a/src/log.cc b/src/log.cc
index 610a63b..c653c14 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1728,10 +1728,18 @@
Handle<String> func_name(shared->DebugName());
if (shared->script()->IsScript()) {
Handle<Script> script(Script::cast(shared->script()));
+ Handle<String> script_name;
if (script->name()->IsString()) {
- Handle<String> script_name(String::cast(script->name()));
+ script_name = Handle<String>(String::cast(script->name()));
+ } else {
+ Handle<Object> name = GetScriptNameOrSourceURL(script);
+ if (!name.is_null() && name->IsString()) {
+ script_name = Handle<String>::cast(name);
+ }
+ }
+ if (!script_name.is_null()) {
int line_num = GetScriptLineNumber(script, shared->start_position());
- if (line_num > 0) {
+ if (line_num > -1) {
PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index dc2db4b..0501ccf 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -148,6 +148,7 @@
VerifyMarking(heap->old_data_space());
VerifyMarking(heap->code_space());
VerifyMarking(heap->cell_space());
+ VerifyMarking(heap->property_cell_space());
VerifyMarking(heap->map_space());
VerifyMarking(heap->new_space());
@@ -229,6 +230,7 @@
VerifyEvacuation(heap->old_data_space());
VerifyEvacuation(heap->code_space());
VerifyEvacuation(heap->cell_space());
+ VerifyEvacuation(heap->property_cell_space());
VerifyEvacuation(heap->map_space());
VerifyEvacuation(heap->new_space());
@@ -283,7 +285,7 @@
array->set_length(length);
}
break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
case JS_PROXY_TYPE:
case JS_VALUE_TYPE:
case TYPE_FEEDBACK_INFO_TYPE:
@@ -375,6 +377,7 @@
if (FLAG_trace_fragmentation) {
TraceFragmentation(heap()->map_space());
TraceFragmentation(heap()->cell_space());
+ TraceFragmentation(heap()->property_cell_space());
}
heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists();
@@ -468,6 +471,7 @@
VerifyMarkbitsAreClean(heap_->old_data_space());
VerifyMarkbitsAreClean(heap_->code_space());
VerifyMarkbitsAreClean(heap_->cell_space());
+ VerifyMarkbitsAreClean(heap_->property_cell_space());
VerifyMarkbitsAreClean(heap_->map_space());
VerifyMarkbitsAreClean(heap_->new_space());
@@ -529,6 +533,7 @@
ClearMarkbitsInPagedSpace(heap_->old_pointer_space());
ClearMarkbitsInPagedSpace(heap_->old_data_space());
ClearMarkbitsInPagedSpace(heap_->cell_space());
+ ClearMarkbitsInPagedSpace(heap_->property_cell_space());
ClearMarkbitsInNewSpace(heap_->new_space());
LargeObjectIterator it(heap_->lo_space());
@@ -648,6 +653,8 @@
case CODE_SPACE: return "CODE_SPACE";
case MAP_SPACE: return "MAP_SPACE";
case CELL_SPACE: return "CELL_SPACE";
+ case PROPERTY_CELL_SPACE:
+ return "PROPERTY_CELL_SPACE";
case LO_SPACE: return "LO_SPACE";
default:
UNREACHABLE();
@@ -1004,7 +1011,7 @@
if (!code_mark.Get()) {
if (FLAG_trace_code_flushing && shared->is_compiled()) {
SmartArrayPointer<char> name = shared->DebugName()->ToCString();
- PrintF("[code-flushing clears: %s]\n", *name);
+ PrintF("[code-flushing clears: %s - age: %d]\n", *name, code->GetAge());
}
shared->set_code(lazy_compile);
candidate->set_code(lazy_compile);
@@ -1045,7 +1052,7 @@
if (!code_mark.Get()) {
if (FLAG_trace_code_flushing && candidate->is_compiled()) {
SmartArrayPointer<char> name = candidate->DebugName()->ToCString();
- PrintF("[code-flushing clears: %s]\n", *name);
+ PrintF("[code-flushing clears: %s - age: %d]\n", *name, code->GetAge());
}
candidate->set_code(lazy_compile);
}
@@ -2148,6 +2155,11 @@
heap()->cell_space());
if (marking_deque_.IsFull()) return;
+ DiscoverGreyObjectsInSpace(heap(),
+ &marking_deque_,
+ heap()->property_cell_space());
+ if (marking_deque_.IsFull()) return;
+
LargeObjectIterator lo_it(heap()->lo_space());
DiscoverGreyObjectsWithIterator(heap(),
&marking_deque_,
@@ -2241,12 +2253,30 @@
HeapObjectIterator cell_iterator(heap()->cell_space());
HeapObject* cell;
while ((cell = cell_iterator.Next()) != NULL) {
+ ASSERT(cell->IsCell());
+ if (IsMarked(cell)) {
+ int offset = Cell::kValueOffset;
+ MarkCompactMarkingVisitor::VisitPointer(
+ heap(),
+ reinterpret_cast<Object**>(cell->address() + offset));
+ }
+ }
+ }
+ {
+ HeapObjectIterator js_global_property_cell_iterator(
+ heap()->property_cell_space());
+ HeapObject* cell;
+ while ((cell = js_global_property_cell_iterator.Next()) != NULL) {
ASSERT(cell->IsJSGlobalPropertyCell());
if (IsMarked(cell)) {
int offset = JSGlobalPropertyCell::kValueOffset;
MarkCompactMarkingVisitor::VisitPointer(
heap(),
reinterpret_cast<Object**>(cell->address() + offset));
+ offset = JSGlobalPropertyCell::kTypeOffset;
+ MarkCompactMarkingVisitor::VisitPointer(
+ heap(),
+ reinterpret_cast<Object**>(cell->address() + offset));
}
}
}
@@ -2418,7 +2448,7 @@
// This map is used for inobject slack tracking and has been detached
// from SharedFunctionInfo during the mark phase.
// Since it survived the GC, reattach it now.
- map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
+ map->unchecked_constructor()->shared()->AttachInitialMap(map);
}
ClearNonLivePrototypeTransitions(map);
@@ -2504,11 +2534,14 @@
int number_of_entries = starts.number_of_entries();
if (number_of_entries == 0) return;
for (int i = 0; i < number_of_entries; i++) {
+ // If the entry is compilation info then the map must be alive,
+ // and ClearAndDeoptimizeDependentCode shouldn't be called.
+ ASSERT(entries->is_code_at(i));
Code* code = entries->code_at(i);
if (IsMarked(code) && !code->marked_for_deoptimization()) {
code->set_marked_for_deoptimization(true);
}
- entries->clear_code_at(i);
+ entries->clear_at(i);
}
map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array()));
}
@@ -2525,15 +2558,17 @@
for (int g = 0; g < DependentCode::kGroupCount; g++) {
int group_number_of_entries = 0;
for (int i = starts.at(g); i < starts.at(g + 1); i++) {
- Code* code = entries->code_at(i);
- if (IsMarked(code) && !code->marked_for_deoptimization()) {
+ Object* obj = entries->object_at(i);
+ ASSERT(obj->IsCode() || IsMarked(obj));
+ if (IsMarked(obj) &&
+ (!obj->IsCode() || !Code::cast(obj)->marked_for_deoptimization())) {
if (new_number_of_entries + group_number_of_entries != i) {
- entries->set_code_at(new_number_of_entries +
- group_number_of_entries, code);
+ entries->set_object_at(
+ new_number_of_entries + group_number_of_entries, obj);
}
- Object** slot = entries->code_slot_at(new_number_of_entries +
- group_number_of_entries);
- RecordSlot(slot, slot, code);
+ Object** slot = entries->slot_at(new_number_of_entries +
+ group_number_of_entries);
+ RecordSlot(slot, slot, obj);
group_number_of_entries++;
}
}
@@ -2543,7 +2578,7 @@
new_number_of_entries += group_number_of_entries;
}
for (int i = new_number_of_entries; i < number_of_entries; i++) {
- entries->clear_code_at(i);
+ entries->clear_at(i);
}
}
@@ -3384,11 +3419,27 @@
for (HeapObject* cell = cell_iterator.Next();
cell != NULL;
cell = cell_iterator.Next()) {
+ if (cell->IsCell()) {
+ Address value_address = reinterpret_cast<Address>(cell) +
+ (Cell::kValueOffset - kHeapObjectTag);
+ updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+ }
+ }
+
+ HeapObjectIterator js_global_property_cell_iterator(
+ heap_->property_cell_space());
+ for (HeapObject* cell = js_global_property_cell_iterator.Next();
+ cell != NULL;
+ cell = js_global_property_cell_iterator.Next()) {
if (cell->IsJSGlobalPropertyCell()) {
Address value_address =
reinterpret_cast<Address>(cell) +
(JSGlobalPropertyCell::kValueOffset - kHeapObjectTag);
updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
+ Address type_address =
+ reinterpret_cast<Address>(cell) +
+ (JSGlobalPropertyCell::kTypeOffset - kHeapObjectTag);
+ updating_visitor.VisitPointer(reinterpret_cast<Object**>(type_address));
}
}
@@ -4050,6 +4101,7 @@
SweepSpace(heap()->code_space(), PRECISE);
SweepSpace(heap()->cell_space(), PRECISE);
+ SweepSpace(heap()->property_cell_space(), PRECISE);
EvacuateNewSpaceAndCandidates();
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 7368ead..2a51b1c 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1998,8 +1998,12 @@
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::INITIAL:
- case Yield::SUSPEND: {
+ case Yield::SUSPEND:
+ // Pop value from top-of-stack slot; box result into result register.
+ EmitCreateIteratorResult(false);
+ __ push(result_register());
+ // Fall through.
+ case Yield::INITIAL: {
VisitForStackValue(expr->generator_object());
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ lw(context_register(),
@@ -2008,12 +2012,8 @@
Label resume;
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&resume, ne, result_register(), Operand(at));
- if (expr->yield_kind() == Yield::SUSPEND) {
- EmitReturnIteratorResult(false);
- } else {
- __ pop(result_register());
- EmitReturnSequence();
- }
+ __ pop(result_register());
+ EmitReturnSequence();
__ bind(&resume);
context()->Plug(result_register());
@@ -2025,7 +2025,10 @@
__ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
__ sw(a1, FieldMemOperand(result_register(),
JSGeneratorObject::kContinuationOffset));
- EmitReturnIteratorResult(true);
+ // Pop value from top-of-stack slot, box result into result register.
+ EmitCreateIteratorResult(true);
+ EmitUnwindBeforeReturn();
+ EmitReturnSequence();
break;
}
@@ -2057,10 +2060,10 @@
// try { received = yield result.value }
__ bind(&l_try);
- __ pop(a0); // result.value
+ EmitCreateIteratorResult(false); // pop and box to v0
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(a0); // result.value
+ __ push(a0); // result
__ lw(a3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g
__ push(a3); // g
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
@@ -2069,7 +2072,8 @@
MemOperand(fp, StandardFrameConstants::kContextOffset));
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&l_resume, ne, a0, Operand(at));
- EmitReturnIteratorResult(false);
+ __ pop(v0); // result
+ EmitReturnSequence();
__ mov(a0, v0);
__ bind(&l_resume); // received in a0
__ PopTryHandler();
@@ -2226,13 +2230,20 @@
}
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Label gc_required;
Label allocated;
Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), a0, a2, a3, &gc_required, TAG_OBJECT);
+ __ jmp(&allocated);
+
+ __ bind(&gc_required);
+ __ Push(Smi::FromInt(map->instance_size()));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ __ lw(context_register(),
+ MemOperand(fp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ li(a1, Operand(map));
@@ -2252,27 +2263,7 @@
// root set.
__ RecordWriteField(a0, JSGeneratorObject::kResultValuePropertyOffset,
a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
-
- if (done) {
- // Exit all nested statements.
- NestedStatement* current = nesting_stack_;
- int stack_depth = 0;
- int context_length = 0;
- while (current != NULL) {
- current = current->Exit(&stack_depth, &context_length);
- }
- __ Drop(stack_depth);
- }
-
__ mov(result_register(), a0);
- EmitReturnSequence();
-
- __ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
- __ lw(context_register(),
- MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ jmp(&allocated);
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 1c8973f..f8d743e 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -87,20 +87,7 @@
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
- for (int i = 0 ; i < prototype_maps_.length(); i++) {
- prototype_maps_.at(i)->AddDependentCode(
- DependentCode::kPrototypeCheckGroup, code);
- }
- for (int i = 0 ; i < transition_maps_.length(); i++) {
- transition_maps_.at(i)->AddDependentCode(
- DependentCode::kTransitionGroup, code);
- }
- if (graph()->depends_on_empty_array_proto_elements()) {
- isolate()->initial_object_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- isolate()->initial_array_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- }
+ info()->CommitDependentMaps(code);
}
@@ -574,27 +561,15 @@
void LCodeGen::WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* pushed_arguments_index,
- int* pushed_arguments_count) {
+ Translation* translation) {
if (environment == NULL) return;
// The translation includes one command per value in the environment.
- int translation_size = environment->values()->length();
+ int translation_size = environment->translation_size();
// The output frame height does not include the parameters.
int height = translation_size - environment->parameter_count();
- // Function parameters are arguments to the outermost environment. The
- // arguments index points to the first element of a sequence of tagged
- // values on the stack that represent the arguments. This needs to be
- // kept in sync with the LArgumentsElements implementation.
- *pushed_arguments_index = -environment->parameter_count();
- *pushed_arguments_count = environment->parameter_count();
-
- WriteTranslation(environment->outer(),
- translation,
- pushed_arguments_index,
- pushed_arguments_count);
+ WriteTranslation(environment->outer(), translation);
bool has_closure_id = !info()->closure().is_null() &&
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
@@ -626,23 +601,6 @@
break;
}
- // Inlined frames which push their arguments cause the index to be
- // bumped and another stack area to be used for materialization,
- // otherwise actual argument values are unknown for inlined frames.
- bool arguments_known = true;
- int arguments_index = *pushed_arguments_index;
- int arguments_count = *pushed_arguments_count;
- if (environment->entry() != NULL) {
- arguments_known = environment->entry()->arguments_pushed();
- arguments_index = arguments_index < 0
- ? GetStackSlotCount() : arguments_index + arguments_count;
- arguments_count = environment->entry()->arguments_count() + 1;
- if (environment->entry()->arguments_pushed()) {
- *pushed_arguments_index = arguments_index;
- *pushed_arguments_count = arguments_count;
- }
- }
-
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either
@@ -654,10 +612,7 @@
AddToTranslation(translation,
environment->spilled_registers()[value->index()],
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
} else if (
value->IsDoubleRegister() &&
environment->spilled_double_registers()[value->index()] != NULL) {
@@ -666,20 +621,36 @@
translation,
environment->spilled_double_registers()[value->index()],
false,
- false,
- arguments_known,
- arguments_index,
- arguments_count);
+ false);
}
}
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsRegister() ||
+ environment->spilled_registers()[value->index()] == NULL);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsDoubleRegister() ||
+ environment->spilled_double_registers()[value->index()] == NULL);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
}
}
@@ -687,17 +658,8 @@
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count) {
- if (op == NULL) {
- // TODO(twuerthinger): Introduce marker operands to indicate that this value
- // is not present and must be reconstructed from the deoptimizer. Currently
- // this is only used for the arguments object.
- translation->StoreArgumentsObject(
- arguments_known, arguments_index, arguments_count);
- } else if (op->IsStackSlot()) {
+ bool is_uint32) {
+ if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
} else if (is_uint32) {
@@ -792,8 +754,6 @@
int frame_count = 0;
int jsframe_count = 0;
- int args_index = 0;
- int args_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
if (e->frame_type() == JS_FUNCTION) {
@@ -801,7 +761,7 @@
}
}
Translation translation(&translations_, frame_count, jsframe_count, zone());
- WriteTranslation(environment, &translation, &args_index, &args_count);
+ WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset();
environment->Register(deoptimization_index,
@@ -1246,8 +1206,10 @@
__ bind(&left_not_min_int);
}
- __ mfhi(result);
- DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
+ if (!instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ __ mfhi(result);
+ DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
+ }
__ mflo(result);
}
@@ -3989,9 +3951,6 @@
}
if (!transition.is_null()) {
- if (transition->CanBeDeprecated()) {
- transition_maps_.Add(transition, info()->zone());
- }
__ li(scratch, Operand(transition));
__ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
@@ -5142,11 +5101,7 @@
ASSERT(prototypes->length() == maps->length());
- if (instr->hydrogen()->CanOmitPrototypeChecks()) {
- for (int i = 0; i < maps->length(); i++) {
- prototype_maps_.Add(maps->at(i), info()->zone());
- }
- } else {
+ if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
for (int i = 0; i < prototypes->length(); i++) {
__ LoadHeapObject(prototype_reg, prototypes->at(i));
__ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index a208c40..a8d7e04 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -55,8 +55,6 @@
deoptimizations_(4, info->zone()),
deopt_jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
- prototype_maps_(0, info->zone()),
- transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -171,10 +169,7 @@
int additional_offset);
// Emit frame translation commands for an environment.
- void WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* arguments_index,
- int* arguments_count);
+ void WriteTranslation(LEnvironment* environment, Translation* translation);
// Declare methods that deal with the individual node types.
#define DECLARE_DO(type) void Do##type(L##type* node);
@@ -297,10 +292,7 @@
void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -412,8 +404,6 @@
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
- ZoneList<Handle<Map> > prototype_maps_;
- ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index ad39c61..889e997 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -933,7 +933,7 @@
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
- int value_count = hydrogen_env->length();
+ int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
LEnvironment* result = new(zone()) LEnvironment(
hydrogen_env->closure(),
hydrogen_env->frame_type(),
@@ -944,13 +944,15 @@
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- for (int i = 0; i < value_count; ++i) {
+ for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
HValue* value = hydrogen_env->values()->at(i);
LOperand* op = NULL;
if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
@@ -962,6 +964,22 @@
value->CheckFlag(HInstruction::kUint32));
}
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ ASSERT(HInstruction::cast(value)->IsLinked());
+ LOperand* op = UseAny(value);
+ result->AddValue(op,
+ value->representation(),
+ value->CheckFlag(HInstruction::kUint32));
+ }
+ }
+
if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index 978ea21..71e9e69 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -172,7 +172,8 @@
int data_space_used,
int code_space_used,
int map_space_used,
- int cell_space_used) {
+ int cell_space_used,
+ int property_cell_space_used) {
fprintf(fp_,
"const int Snapshot::%snew_space_used_ = %d;\n",
prefix,
@@ -197,6 +198,10 @@
"const int Snapshot::%scell_space_used_ = %d;\n",
prefix,
cell_space_used);
+ fprintf(fp_,
+ "const int Snapshot::%sproperty_cell_space_used_ = %d;\n",
+ prefix,
+ property_cell_space_used);
}
void WritePartialSnapshot() {
@@ -417,7 +422,8 @@
partial_ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
partial_ser.CurrentAllocationAddress(i::CODE_SPACE),
partial_ser.CurrentAllocationAddress(i::MAP_SPACE),
- partial_ser.CurrentAllocationAddress(i::CELL_SPACE));
+ partial_ser.CurrentAllocationAddress(i::CELL_SPACE),
+ partial_ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
sink.WriteSpaceUsed(
"",
ser.CurrentAllocationAddress(i::NEW_SPACE),
@@ -425,6 +431,7 @@
ser.CurrentAllocationAddress(i::OLD_DATA_SPACE),
ser.CurrentAllocationAddress(i::CODE_SPACE),
ser.CurrentAllocationAddress(i::MAP_SPACE),
- ser.CurrentAllocationAddress(i::CELL_SPACE));
+ ser.CurrentAllocationAddress(i::CELL_SPACE),
+ ser.CurrentAllocationAddress(i::PROPERTY_CELL_SPACE));
return 0;
}
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 4008181..3b561ee 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -163,7 +163,10 @@
case JS_BUILTINS_OBJECT_TYPE:
JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
+ Cell::cast(this)->CellVerify();
+ break;
+ case PROPERTY_CELL_TYPE:
JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify();
break;
case JS_ARRAY_TYPE:
@@ -615,9 +618,16 @@
}
+void Cell::CellVerify() {
+ CHECK(IsCell());
+ VerifyObjectField(kValueOffset);
+}
+
+
void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
CHECK(IsJSGlobalPropertyCell());
VerifyObjectField(kValueOffset);
+ VerifyObjectField(kTypeOffset);
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index e60f0f3..24af123 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -668,7 +668,8 @@
TYPE_CHECKER(Code, CODE_TYPE)
TYPE_CHECKER(Oddball, ODDBALL_TYPE)
-TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
+TYPE_CHECKER(Cell, CELL_TYPE)
+TYPE_CHECKER(JSGlobalPropertyCell, PROPERTY_CELL_TYPE)
TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
@@ -1621,18 +1622,28 @@
}
-Object* JSGlobalPropertyCell::value() {
+Object* Cell::value() {
return READ_FIELD(this, kValueOffset);
}
-void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
+void Cell::set_value(Object* val, WriteBarrierMode ignored) {
// The write barrier is not used for global property cells.
- ASSERT(!val->IsJSGlobalPropertyCell());
+ ASSERT(!val->IsJSGlobalPropertyCell() && !val->IsCell());
WRITE_FIELD(this, kValueOffset, val);
}
+Object* JSGlobalPropertyCell::type_raw() {
+ return READ_FIELD(this, kTypeOffset);
+}
+
+
+void JSGlobalPropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
+ WRITE_FIELD(this, kTypeOffset, val);
+}
+
+
int JSObject::GetHeaderSize() {
InstanceType type = map()->instance_type();
// Check for the most common kind of JavaScript object before
@@ -2552,6 +2563,7 @@
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(Oddball)
+CAST_ACCESSOR(Cell)
CAST_ACCESSOR(JSGlobalPropertyCell)
CAST_ACCESSOR(SharedFunctionInfo)
CAST_ACCESSOR(Map)
@@ -3659,17 +3671,6 @@
}
-void Map::AddDependentCode(DependentCode::DependencyGroup group,
- Handle<Code> code) {
- Handle<DependentCode> codes =
- DependentCode::Insert(Handle<DependentCode>(dependent_code()),
- group, code);
- if (*codes != dependent_code()) {
- set_dependent_code(*codes);
- }
-}
-
-
int DependentCode::number_of_entries(DependencyGroup group) {
if (length() == 0) return 0;
return Smi::cast(get(group))->value();
@@ -3681,32 +3682,52 @@
}
+bool DependentCode::is_code_at(int i) {
+ return get(kCodesStartIndex + i)->IsCode();
+}
+
Code* DependentCode::code_at(int i) {
return Code::cast(get(kCodesStartIndex + i));
}
-void DependentCode::set_code_at(int i, Code* value) {
- set(kCodesStartIndex + i, value);
+CompilationInfo* DependentCode::compilation_info_at(int i) {
+ return reinterpret_cast<CompilationInfo*>(
+ Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
}
-Object** DependentCode::code_slot_at(int i) {
+void DependentCode::set_object_at(int i, Object* object) {
+ set(kCodesStartIndex + i, object);
+}
+
+
+Object* DependentCode::object_at(int i) {
+ return get(kCodesStartIndex + i);
+}
+
+
+Object** DependentCode::slot_at(int i) {
return HeapObject::RawField(
this, FixedArray::OffsetOfElementAt(kCodesStartIndex + i));
}
-void DependentCode::clear_code_at(int i) {
+void DependentCode::clear_at(int i) {
set_undefined(kCodesStartIndex + i);
}
+void DependentCode::copy(int from, int to) {
+ set(kCodesStartIndex + to, get(kCodesStartIndex + from));
+}
+
+
void DependentCode::ExtendGroup(DependencyGroup group) {
GroupStartIndexes starts(this);
for (int g = kGroupCount - 1; g > group; g--) {
if (starts.at(g) < starts.at(g + 1)) {
- set_code_at(starts.at(g + 1), code_at(starts.at(g)));
+ copy(starts.at(g), starts.at(g + 1));
}
}
}
@@ -4960,12 +4981,6 @@
}
-SharedFunctionInfo* JSFunction::unchecked_shared() {
- return reinterpret_cast<SharedFunctionInfo*>(
- READ_FIELD(this, kSharedFunctionInfoOffset));
-}
-
-
void JSFunction::set_context(Object* value) {
ASSERT(value->IsUndefined() || value->IsContext());
WRITE_FIELD(this, kContextOffset, value);
@@ -6011,13 +6026,13 @@
}
-void TypeFeedbackCells::SetCell(int index, JSGlobalPropertyCell* cell) {
+void TypeFeedbackCells::SetCell(int index, Cell* cell) {
set(index * 2, cell);
}
-JSGlobalPropertyCell* TypeFeedbackCells::Cell(int index) {
- return JSGlobalPropertyCell::cast(get(index * 2));
+Cell* TypeFeedbackCells::GetCell(int index) {
+ return Cell::cast(get(index * 2));
}
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 357d984..33aa404 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -182,7 +182,10 @@
case JS_MESSAGE_OBJECT_TYPE:
JSMessageObject::cast(this)->JSMessageObjectPrint(out);
break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
+ Cell::cast(this)->CellPrint(out);
+ break;
+ case PROPERTY_CELL_TYPE:
JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
break;
case JS_ARRAY_BUFFER_TYPE:
@@ -533,7 +536,8 @@
case JS_OBJECT_TYPE: return "JS_OBJECT";
case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
case ODDBALL_TYPE: return "ODDBALL";
- case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
+ case CELL_TYPE: return "CELL";
+ case PROPERTY_CELL_TYPE: return "PROPERTY_CELL";
case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
case JS_GENERATOR_OBJECT_TYPE: return "JS_GENERATOR_OBJECT";
case JS_MODULE_TYPE: return "JS_MODULE";
@@ -917,6 +921,11 @@
}
+void Cell::CellPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Cell");
+}
+
+
void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
}
@@ -1093,8 +1102,8 @@
void AllocationSiteInfo::AllocationSiteInfoPrint(FILE* out) {
HeapObject::PrintHeader(out, "AllocationSiteInfo");
PrintF(out, " - payload: ");
- if (payload()->IsJSGlobalPropertyCell()) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(payload());
+ if (payload()->IsCell()) {
+ Cell* cell = Cell::cast(payload());
Object* cell_contents = cell->value();
if (cell_contents->IsSmi()) {
ElementsKind kind = static_cast<ElementsKind>(
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index 829eab8..c138fdd 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -196,6 +196,11 @@
// Registration for kVisitJSRegExp is done by StaticVisitor.
+ table_.Register(kVisitCell,
+ &FixedBodyVisitor<StaticVisitor,
+ Cell::BodyDescriptor,
+ void>::Visit);
+
table_.Register(kVisitPropertyCell,
&FixedBodyVisitor<StaticVisitor,
JSGlobalPropertyCell::BodyDescriptor,
@@ -240,10 +245,10 @@
template<typename StaticVisitor>
-void StaticMarkingVisitor<StaticVisitor>::VisitGlobalPropertyCell(
+void StaticMarkingVisitor<StaticVisitor>::VisitCell(
Heap* heap, RelocInfo* rinfo) {
- ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
- JSGlobalPropertyCell* cell = rinfo->target_cell();
+ ASSERT(rinfo->rmode() == RelocInfo::CELL);
+ Cell* cell = rinfo->target_cell();
StaticVisitor::MarkObject(heap, cell);
}
@@ -414,7 +419,7 @@
// Visit shared function info immediately to avoid double checking
// of its flushability later. This is just an optimization because
// the shared function info would eventually be visited.
- SharedFunctionInfo* shared = function->unchecked_shared();
+ SharedFunctionInfo* shared = function->shared();
if (StaticVisitor::MarkObjectWithoutPush(heap, shared)) {
StaticVisitor::MarkObject(heap, shared->map());
VisitSharedFunctionInfoWeakCode(heap, shared);
@@ -595,7 +600,7 @@
template<typename StaticVisitor>
bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(
Heap* heap, JSFunction* function) {
- SharedFunctionInfo* shared_info = function->unchecked_shared();
+ SharedFunctionInfo* shared_info = function->shared();
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
@@ -777,7 +782,7 @@
void Code::CodeIterateBody(ObjectVisitor* v) {
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
- RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+ RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
@@ -801,7 +806,7 @@
void Code::CodeIterateBody(Heap* heap) {
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
- RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+ RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 4bf2804..686cacf 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -91,7 +91,10 @@
case CODE_TYPE:
return kVisitCode;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
+ return kVisitCell;
+
+ case PROPERTY_CELL_TYPE:
return kVisitPropertyCell;
case JS_SET_TYPE:
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index c4d1cc3..f347c87 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -88,6 +88,7 @@
V(Oddball) \
V(Code) \
V(Map) \
+ V(Cell) \
V(PropertyCell) \
V(SharedFunctionInfo) \
V(JSFunction) \
@@ -394,7 +395,7 @@
INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address));
INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo));
- INLINE(static void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo));
+ INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitDebugTarget(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo));
INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo));
diff --git a/src/objects.cc b/src/objects.cc
index 6512c60..5459679 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -631,7 +631,7 @@
if (IsGlobalObject()) {
value = JSGlobalPropertyCell::cast(value)->value();
}
- ASSERT(!value->IsJSGlobalPropertyCell());
+ ASSERT(!value->IsJSGlobalPropertyCell() && !value->IsCell());
return value;
}
@@ -639,9 +639,8 @@
Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
ASSERT(!HasFastProperties());
if (IsGlobalObject()) {
- JSGlobalPropertyCell* cell =
- JSGlobalPropertyCell::cast(
- property_dictionary()->ValueAt(result->GetDictionaryEntry()));
+ JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
+ property_dictionary()->ValueAt(result->GetDictionaryEntry()));
cell->set_value(value);
} else {
property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
@@ -1385,7 +1384,7 @@
global_object ? "Global Object: " : "",
vowel ? "n" : "");
accumulator->Put(str);
- accumulator->Add(" with %smap 0x%p",
+ accumulator->Add(" with %smap %p",
map_of_this->is_deprecated() ? "deprecated " : "",
map_of_this);
printed = true;
@@ -1567,8 +1566,12 @@
case FOREIGN_TYPE:
accumulator->Add("<Foreign>");
break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
accumulator->Add("Cell for ");
+ Cell::cast(this)->value()->ShortPrint(accumulator);
+ break;
+ case PROPERTY_CELL_TYPE:
+ accumulator->Add("PropertyCell for ");
JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
break;
default:
@@ -1661,7 +1664,10 @@
case CODE_TYPE:
reinterpret_cast<Code*>(this)->CodeIterateBody(v);
break;
- case JS_GLOBAL_PROPERTY_CELL_TYPE:
+ case CELL_TYPE:
+ Cell::BodyDescriptor::IterateBody(this, v);
+ break;
+ case PROPERTY_CELL_TYPE:
JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
break;
case SYMBOL_TYPE:
@@ -8905,8 +8911,8 @@
bool AllocationSiteInfo::GetElementsKindPayload(ElementsKind* kind) {
ASSERT(kind != NULL);
- if (payload()->IsJSGlobalPropertyCell()) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(payload());
+ if (payload()->IsCell()) {
+ Cell* cell = Cell::cast(payload());
Object* cell_contents = cell->value();
if (cell_contents->IsSmi()) {
*kind = static_cast<ElementsKind>(
@@ -9980,13 +9986,13 @@
}
-void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
- ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
+void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
+ ASSERT(rinfo->rmode() == RelocInfo::CELL);
Object* cell = rinfo->target_cell();
Object* old_cell = cell;
VisitPointer(&cell);
if (cell != old_cell) {
- rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
+ rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
}
}
@@ -10012,7 +10018,7 @@
VisitExternalReferences(p, p + 1);
}
-byte Code::compare_nil_types() {
+byte Code::compare_nil_state() {
ASSERT(is_compare_nil_ic_stub());
return CompareNilICStub::ExtractTypesFromExtraICState(
extended_extra_ic_state());
@@ -10048,7 +10054,7 @@
intptr_t delta = instruction_start() - desc.buffer;
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
- RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
+ RelocInfo::ModeMask(RelocInfo::CELL) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
RelocInfo::kApplyMask;
// Needed to find target_object and runtime_entry on X64
@@ -10059,8 +10065,8 @@
if (mode == RelocInfo::EMBEDDED_OBJECT) {
Handle<Object> p = it.rinfo()->target_object_handle(origin);
it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle();
+ } else if (mode == RelocInfo::CELL) {
+ Handle<Cell> cell = it.rinfo()->target_cell_handle();
it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
} else if (RelocInfo::IsCodeTarget(mode)) {
// rewrite code handles in inline cache targets to direct
@@ -10246,7 +10252,7 @@
TypeFeedbackCells* type_feedback_cells =
TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
- JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
+ Cell* cell = type_feedback_cells->GetCell(i);
cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
}
}
@@ -10299,6 +10305,18 @@
}
+int Code::GetAge() {
+ byte* sequence = FindCodeAgeSequence();
+ if (sequence == NULL) {
+ return Code::kNoAge;
+ }
+ Age age;
+ MarkingParity parity;
+ GetCodeAgeAndParity(sequence, &age, &parity);
+ return age;
+}
+
+
void Code::GetCodeAgeAndParity(Code* code, Age* age,
MarkingParity* parity) {
Isolate* isolate = Isolate::Current();
@@ -10538,11 +10556,8 @@
}
case Translation::ARGUMENTS_OBJECT: {
- bool args_known = iterator.Next();
- int args_index = iterator.Next();
int args_length = iterator.Next();
- PrintF(out, "{index=%d, length=%d, known=%d}",
- args_index, args_length, args_known);
+ PrintF(out, "{length=%d}", args_length);
break;
}
}
@@ -11091,6 +11106,24 @@
}
+void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
+ CompilationInfo* info) {
+ Handle<DependentCode> dep(dependent_code());
+ Handle<DependentCode> codes =
+ DependentCode::Insert(dep, group, info->object_wrapper());
+ if (*codes != dependent_code()) set_dependent_code(*codes);
+ info->dependent_maps(group)->Add(Handle<Map>(this), info->zone());
+}
+
+
+void Map::AddDependentCode(DependentCode::DependencyGroup group,
+ Handle<Code> code) {
+ Handle<DependentCode> codes = DependentCode::Insert(
+ Handle<DependentCode>(dependent_code()), group, code);
+ if (*codes != dependent_code()) set_dependent_code(*codes);
+}
+
+
DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
Recompute(entries);
}
@@ -11107,13 +11140,13 @@
Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
DependencyGroup group,
- Handle<Code> value) {
+ Handle<Object> object) {
GroupStartIndexes starts(*entries);
int start = starts.at(group);
int end = starts.at(group + 1);
int number_of_entries = starts.number_of_entries();
- if (start < end && entries->code_at(end - 1) == *value) {
- // Do not append the code if it is already in the array.
+ if (start < end && entries->object_at(end - 1) == *object) {
+ // Do not append the compilation info if it is already in the array.
// It is sufficient to just check only the last element because
// we process embedded maps of an optimized code in one batch.
return entries;
@@ -11130,7 +11163,7 @@
end = starts.at(group + 1);
number_of_entries = starts.number_of_entries();
for (int i = 0; i < number_of_entries; i++) {
- entries->clear_code_at(i);
+ entries->clear_at(i);
}
// If the old fixed array was empty, we need to reset counters of the
// new array.
@@ -11142,17 +11175,79 @@
entries = new_entries;
}
entries->ExtendGroup(group);
- entries->set_code_at(end, *value);
+ entries->set_object_at(end, *object);
entries->set_number_of_entries(group, end + 1 - start);
return entries;
}
+void DependentCode::UpdateToFinishedCode(DependencyGroup group,
+ CompilationInfo* info,
+ Code* code) {
+ DisallowHeapAllocation no_gc;
+ AllowDeferredHandleDereference get_object_wrapper;
+ Foreign* info_wrapper = *info->object_wrapper();
+ GroupStartIndexes starts(this);
+ int start = starts.at(group);
+ int end = starts.at(group + 1);
+ for (int i = start; i < end; i++) {
+ if (object_at(i) == info_wrapper) {
+ set_object_at(i, code);
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ for (int i = start; i < end; i++) {
+ ASSERT(is_code_at(i) || compilation_info_at(i) != info);
+ }
+#endif
+}
+
+
+void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
+ CompilationInfo* info) {
+ DisallowHeapAllocation no_allocation;
+ AllowDeferredHandleDereference get_object_wrapper;
+ Foreign* info_wrapper = *info->object_wrapper();
+ GroupStartIndexes starts(this);
+ int start = starts.at(group);
+ int end = starts.at(group + 1);
+ // Find compilation info wrapper.
+ int info_pos = -1;
+ for (int i = start; i < end; i++) {
+ if (object_at(i) == info_wrapper) {
+ info_pos = i;
+ break;
+ }
+ }
+ if (info_pos == -1) return; // Not found.
+ int gap = info_pos;
+ // Use the last of each group to fill the gap in the previous group.
+ for (int i = group; i < kGroupCount; i++) {
+ int last_of_group = starts.at(i + 1) - 1;
+ ASSERT(last_of_group >= gap);
+ if (last_of_group == gap) continue;
+ copy(last_of_group, gap);
+ gap = last_of_group;
+ }
+ ASSERT(gap == starts.number_of_entries() - 1);
+ clear_at(gap); // Clear last gap.
+ set_number_of_entries(group, end - start - 1);
+
+#ifdef DEBUG
+ for (int i = start; i < end - 1; i++) {
+ ASSERT(is_code_at(i) || compilation_info_at(i) != info);
+ }
+#endif
+}
+
+
bool DependentCode::Contains(DependencyGroup group, Code* code) {
GroupStartIndexes starts(this);
- int number_of_entries = starts.at(kGroupCount);
+ int number_of_entries = starts.number_of_entries();
for (int i = 0; i < number_of_entries; i++) {
- if (code_at(i) == code) return true;
+ if (object_at(i) == code) return true;
}
return false;
}
@@ -11173,20 +11268,25 @@
DependentCode::GroupStartIndexes starts(this);
int start = starts.at(group);
int end = starts.at(group + 1);
- int number_of_entries = starts.at(DependentCode::kGroupCount);
+ int code_entries = starts.number_of_entries();
if (start == end) return;
for (int i = start; i < end; i++) {
- Code* code = code_at(i);
- code->set_marked_for_deoptimization(true);
+ if (is_code_at(i)) {
+ Code* code = code_at(i);
+ code->set_marked_for_deoptimization(true);
+ } else {
+ CompilationInfo* info = compilation_info_at(i);
+ info->AbortDueToDependentMap();
+ }
}
// Compact the array by moving all subsequent groups to fill in the new holes.
- for (int src = end, dst = start; src < number_of_entries; src++, dst++) {
- set_code_at(dst, code_at(src));
+ for (int src = end, dst = start; src < code_entries; src++, dst++) {
+ copy(src, dst);
}
// Now the holes are at the end of the array, zap them for heap-verifier.
int removed = end - start;
- for (int i = number_of_entries - removed; i < number_of_entries; i++) {
- clear_code_at(i);
+ for (int i = code_entries - removed; i < code_entries; i++) {
+ clear_at(i);
}
set_number_of_entries(group, 0);
DeoptimizeDependentCodeFilter filter;
@@ -12236,8 +12336,8 @@
return payload->TransitionElementsKind(to_kind);
}
}
- } else if (info->payload()->IsJSGlobalPropertyCell()) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(info->payload());
+ } else if (info->payload()->IsCell()) {
+ Cell* cell = Cell::cast(info->payload());
Object* cell_contents = cell->value();
if (cell_contents->IsSmi()) {
ElementsKind kind = static_cast<ElementsKind>(
@@ -15710,4 +15810,15 @@
set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
}
+
+Type* JSGlobalPropertyCell::type() {
+ return static_cast<Type*>(type_raw());
+}
+
+
+void JSGlobalPropertyCell::set_type(Type* type, WriteBarrierMode ignored) {
+ set_type_raw(type, ignored);
+}
+
+
} } // namespace v8::internal
diff --git a/src/objects.h b/src/objects.h
index 1ee31b6..7771eb4 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -119,6 +119,8 @@
// - ExternalTwoByteInternalizedString
// - Symbol
// - HeapNumber
+// - Cell
+// - JSGlobalPropertyCell
// - Code
// - Map
// - Oddball
@@ -348,7 +350,8 @@
V(MAP_TYPE) \
V(CODE_TYPE) \
V(ODDBALL_TYPE) \
- V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
+ V(CELL_TYPE) \
+ V(PROPERTY_CELL_TYPE) \
V(BOX_TYPE) \
\
V(HEAP_NUMBER_TYPE) \
@@ -669,7 +672,8 @@
MAP_TYPE,
CODE_TYPE,
ODDBALL_TYPE,
- JS_GLOBAL_PROPERTY_CELL_TYPE,
+ CELL_TYPE,
+ PROPERTY_CELL_TYPE,
BOX_TYPE,
// "Data", objects that cannot contain non-map-word pointers to heap
@@ -841,6 +845,7 @@
class FixedArrayBase;
class ObjectVisitor;
class StringStream;
+class Type;
struct ValueInfo : public Malloced {
ValueInfo() : type(FIRST_TYPE), ptr(NULL), str(NULL), number(0) { }
@@ -1011,6 +1016,7 @@
V(JSGlobalProxy) \
V(UndetectableObject) \
V(AccessCheckNeeded) \
+ V(Cell) \
V(JSGlobalPropertyCell) \
V(ObjectHashTable) \
@@ -4378,6 +4384,7 @@
// Forward declaration.
+class Cell;
class JSGlobalPropertyCell;
// TypeFeedbackCells is a fixed array used to hold the association between
@@ -4395,8 +4402,8 @@
inline void SetAstId(int index, TypeFeedbackId id);
// Accessors for global property cells holding the cache values.
- inline JSGlobalPropertyCell* Cell(int index);
- inline void SetCell(int index, JSGlobalPropertyCell* cell);
+ inline Cell* GetCell(int index);
+ inline void SetCell(int index, Cell* cell);
// The object that indicates an uninitialized cache.
static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
@@ -4662,7 +4669,7 @@
inline byte to_boolean_state();
// [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in.
- byte compare_nil_types();
+ byte compare_nil_state();
// [has_function_cache]: For kind STUB tells whether there is a function
// cache is passed to the stub.
@@ -4825,6 +4832,7 @@
void MakeOlder(MarkingParity);
static bool IsYoungSequence(byte* sequence);
bool IsOld();
+ int GetAge();
void PrintDeoptLocation(int bailout_id);
@@ -4966,8 +4974,8 @@
// Code aging
byte* FindCodeAgeSequence();
- static void GetCodeAgeAndParity(Code* code, Age* age,
- MarkingParity* parity);
+ static void GetCodeAgeAndParity(Code* code, Age* age,
+ MarkingParity* parity);
static void GetCodeAgeAndParity(byte* sequence, Age* age,
MarkingParity* parity);
static Code* GetCodeAgeStub(Age age, MarkingParity parity);
@@ -4980,6 +4988,8 @@
};
+class CompilationInfo;
+
// This class describes the layout of dependent codes array of a map. The
// array is partitioned into several groups of dependent codes. Each group
// contains codes with the same dependency on the map. The array has the
@@ -5033,8 +5043,14 @@
bool Contains(DependencyGroup group, Code* code);
static Handle<DependentCode> Insert(Handle<DependentCode> entries,
- DependencyGroup group,
- Handle<Code> value);
+ DependencyGroup group,
+ Handle<Object> object);
+ void UpdateToFinishedCode(DependencyGroup group,
+ CompilationInfo* info,
+ Code* code);
+ void RemoveCompilationInfo(DependentCode::DependencyGroup group,
+ CompilationInfo* info);
+
void DeoptimizeDependentCodeGroup(Isolate* isolate,
DependentCode::DependencyGroup group);
@@ -5042,10 +5058,14 @@
// and the mark compact collector.
inline int number_of_entries(DependencyGroup group);
inline void set_number_of_entries(DependencyGroup group, int value);
+ inline bool is_code_at(int i);
inline Code* code_at(int i);
- inline void set_code_at(int i, Code* value);
- inline Object** code_slot_at(int i);
- inline void clear_code_at(int i);
+ inline CompilationInfo* compilation_info_at(int i);
+ inline void set_object_at(int i, Object* object);
+ inline Object** slot_at(int i);
+ inline Object* object_at(int i);
+ inline void clear_at(int i);
+ inline void copy(int from, int to);
static inline DependentCode* cast(Object* object);
private:
@@ -5388,7 +5408,7 @@
set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
}
- inline JSGlobalPropertyCell* RetrieveDescriptorsPointer();
+ inline Cell* RetrieveDescriptorsPointer();
int EnumLength() {
return EnumLengthBits::decode(bit_field3());
@@ -5554,8 +5574,11 @@
inline bool CanOmitPrototypeChecks();
- inline void AddDependentCode(DependentCode::DependencyGroup group,
- Handle<Code> code);
+ void AddDependentCompilationInfo(DependentCode::DependencyGroup group,
+ CompilationInfo* info);
+
+ void AddDependentCode(DependentCode::DependencyGroup group,
+ Handle<Code> code);
bool IsMapInArrayPrototypeChain();
@@ -6565,8 +6588,6 @@
// can be shared by instances.
DECL_ACCESSORS(shared, SharedFunctionInfo)
- inline SharedFunctionInfo* unchecked_shared();
-
// [context]: The context for this function.
inline Context* context();
inline Object* unchecked_context();
@@ -8539,16 +8560,18 @@
};
-class JSGlobalPropertyCell: public HeapObject {
+class Cell: public HeapObject {
public:
// [value]: value of the global property.
DECL_ACCESSORS(value, Object)
// Casting.
- static inline JSGlobalPropertyCell* cast(Object* obj);
+ static inline Cell* cast(Object* obj);
- static inline JSGlobalPropertyCell* FromValueAddress(Address value) {
- return cast(FromAddress(value - kValueOffset));
+ static inline Cell* FromValueAddress(Address value) {
+ Object* result = FromAddress(value - kValueOffset);
+ ASSERT(result->IsCell() || result->IsJSGlobalPropertyCell());
+ return static_cast<Cell*>(result);
}
inline Address ValueAddress() {
@@ -8556,8 +8579,8 @@
}
// Dispatched behavior.
- DECLARE_PRINTER(JSGlobalPropertyCell)
- DECLARE_VERIFIER(JSGlobalPropertyCell)
+ DECLARE_PRINTER(Cell)
+ DECLARE_VERIFIER(Cell)
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
@@ -8568,6 +8591,37 @@
kSize> BodyDescriptor;
private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Cell);
+};
+
+
+class JSGlobalPropertyCell: public Cell {
+ public:
+ Type* type();
+ void set_type(Type* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+
+ // Casting.
+ static inline JSGlobalPropertyCell* cast(Object* obj);
+
+ inline Address TypeAddress() {
+ return address() + kTypeOffset;
+ }
+
+ // Dispatched behavior.
+ DECLARE_PRINTER(JSGlobalPropertyCell)
+ DECLARE_VERIFIER(JSGlobalPropertyCell)
+
+ // Layout description.
+ static const int kTypeOffset = kValueOffset + kPointerSize;
+ static const int kSize = kTypeOffset + kPointerSize;
+
+ typedef FixedBodyDescriptor<
+ kValueOffset,
+ kTypeOffset + kPointerSize,
+ JSGlobalPropertyCell::kSize> BodyDescriptor;
+
+ private:
+ DECL_ACCESSORS(type_raw, Object)
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
};
@@ -9587,7 +9641,7 @@
virtual void VisitCodeEntry(Address entry_address);
// Visits a global property cell reference in the instruction stream.
- virtual void VisitGlobalPropertyCell(RelocInfo* rinfo);
+ virtual void VisitCell(RelocInfo* rinfo);
// Visits a runtime entry in the instruction stream.
virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
diff --git a/src/parser.cc b/src/parser.cc
index fa24bf7..996d677 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2624,11 +2624,13 @@
}
-bool Parser::CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
+bool Parser::CheckInOrOf(bool accept_OF,
+ ForEachStatement::VisitMode* visit_mode) {
if (Check(Token::IN)) {
*visit_mode = ForEachStatement::ENUMERATE;
return true;
- } else if (allow_for_of() && CheckContextualKeyword(CStrVector("of"))) {
+ } else if (allow_for_of() && accept_OF &&
+ CheckContextualKeyword(CStrVector("of"))) {
*visit_mode = ForEachStatement::ITERATE;
return true;
}
@@ -2726,11 +2728,14 @@
if (peek() == Token::VAR || peek() == Token::CONST) {
bool is_const = peek() == Token::CONST;
Handle<String> name;
+ VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
- ParseVariableDeclarations(kForStatement, NULL, NULL, &name, CHECK_OK);
+ ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
+ CHECK_OK);
+ bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
- if (!name.is_null() && CheckInOrOf(&mode)) {
+ if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
Interface* interface =
is_const ? Interface::NewConst() : Interface::NewValue();
ForEachStatement* loop = factory()->NewForEachStatement(mode, labels);
@@ -2762,9 +2767,10 @@
ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
CHECK_OK);
bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+ bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode;
- if (accept_IN && CheckInOrOf(&mode)) {
+ if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
// Rewrite a for-in statement of the form
//
// for (let x in e) b
@@ -2820,8 +2826,9 @@
} else {
Expression* expression = ParseExpression(false, CHECK_OK);
ForEachStatement::VisitMode mode;
+ bool accept_OF = expression->AsVariableProxy();
- if (CheckInOrOf(&mode)) {
+ if (CheckInOrOf(accept_OF, &mode)) {
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
// error here but for compatibility with JSC we choose to report
diff --git a/src/parser.h b/src/parser.h
index b7e0700..38633b0 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -729,7 +729,7 @@
bool is_generator() const { return current_function_state_->is_generator(); }
- bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode);
+ bool CheckInOrOf(bool accept_OF, ForEachStatement::VisitMode* visit_mode);
bool peek_any_identifier();
diff --git a/src/preparser.cc b/src/preparser.cc
index 828177a..3268e3c 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -659,10 +659,9 @@
}
-bool PreParser::CheckInOrOf() {
+bool PreParser::CheckInOrOf(bool accept_OF) {
if (peek() == i::Token::IN ||
- (allow_for_of() &&
- peek() == i::Token::IDENTIFIER &&
+ (allow_for_of() && accept_OF && peek() == i::Token::IDENTIFIER &&
scanner_->is_next_contextual_keyword(v8::internal::CStrVector("of")))) {
Next();
return true;
@@ -685,9 +684,10 @@
VariableDeclarationProperties decl_props = kHasNoInitializers;
ParseVariableDeclarations(
kForStatement, &decl_props, &decl_count, CHECK_OK);
- bool accept_IN = decl_count == 1 &&
- !(is_let && decl_props == kHasInitializers);
- if (accept_IN && CheckInOrOf()) {
+ bool has_initializers = decl_props == kHasInitializers;
+ bool accept_IN = decl_count == 1 && !(is_let && has_initializers);
+ bool accept_OF = !has_initializers;
+ if (accept_IN && CheckInOrOf(accept_OF)) {
ParseExpression(true, CHECK_OK);
Expect(i::Token::RPAREN, CHECK_OK);
@@ -695,8 +695,8 @@
return Statement::Default();
}
} else {
- ParseExpression(false, CHECK_OK);
- if (CheckInOrOf()) {
+ Expression lhs = ParseExpression(false, CHECK_OK);
+ if (CheckInOrOf(lhs.IsIdentifier())) {
ParseExpression(true, CHECK_OK);
Expect(i::Token::RPAREN, CHECK_OK);
diff --git a/src/preparser.h b/src/preparser.h
index 786316e..41907d1 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -658,7 +658,7 @@
}
void ExpectSemicolon(bool* ok);
- bool CheckInOrOf();
+ bool CheckInOrOf(bool accept_OF);
static int Precedence(i::Token::Value tok, bool accept_IN);
diff --git a/src/runtime.cc b/src/runtime.cc
index eccf6ea..8711764 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -691,7 +691,7 @@
array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
isolate->heap()->set_array_buffers_list(*array_buffer);
- array_buffer->set_weak_first_array(Smi::FromInt(0));
+ array_buffer->set_weak_first_array(isolate->heap()->undefined_value());
}
@@ -8097,13 +8097,15 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WaitUntilOptimized) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CompleteOptimization) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- if (FLAG_parallel_recompilation) {
- if (V8::UseCrankshaft() && function->IsOptimizable()) {
- while (!function->IsOptimized()) OS::Sleep(50);
+ if (FLAG_parallel_recompilation && V8::UseCrankshaft()) {
+ // While function is in optimization pipeline, it is marked with builtins.
+ while (function->code()->kind() == Code::BUILTIN) {
+ isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
+ OS::Sleep(50);
}
}
return isolate->heap()->undefined_value();
@@ -13479,9 +13481,9 @@
MaybeObject* maybe_array;
if (!type_info.is_null() &&
*type_info != isolate->heap()->undefined_value() &&
- JSGlobalPropertyCell::cast(*type_info)->value()->IsSmi() &&
+ Cell::cast(*type_info)->value()->IsSmi() &&
can_use_type_feedback) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info);
+ Cell* cell = Cell::cast(*type_info);
Smi* smi = Smi::cast(cell->value());
ElementsKind to_kind = static_cast<ElementsKind>(smi->value());
if (holey && !IsFastHoleyElementsKind(to_kind)) {
diff --git a/src/runtime.h b/src/runtime.h
index ef54016..c52bbe7 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -96,7 +96,7 @@
F(ClearFunctionTypeFeedback, 1, 1) \
F(RunningInSimulator, 0, 1) \
F(OptimizeFunctionOnNextCall, -1, 1) \
- F(WaitUntilOptimized, 1, 1) \
+ F(CompleteOptimization, 1, 1) \
F(GetOptimizationStatus, 1, 1) \
F(GetOptimizationCount, 1, 1) \
F(CompileForOnStackReplacement, 1, 1) \
diff --git a/src/serialize.cc b/src/serialize.cc
index 6c5ccea..4e51cd3 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -687,6 +687,8 @@
isolate_->heap()->set_native_contexts_list(
isolate_->heap()->undefined_value());
+ isolate_->heap()->set_array_buffers_list(
+ isolate_->heap()->undefined_value());
// Update data pointers to the external strings containing natives sources.
for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
@@ -776,6 +778,7 @@
bool write_barrier_needed = (current_object_address != NULL &&
source_space != NEW_SPACE &&
source_space != CELL_SPACE &&
+ source_space != PROPERTY_CELL_SPACE &&
source_space != CODE_SPACE &&
source_space != OLD_DATA_SPACE);
while (current < limit) {
@@ -836,8 +839,7 @@
new_code_object->instruction_start()); \
} else { \
ASSERT(space_number == CODE_SPACE); \
- JSGlobalPropertyCell* cell = \
- JSGlobalPropertyCell::cast(new_object); \
+ Cell* cell = Cell::cast(new_object); \
new_object = reinterpret_cast<Object*>( \
cell->ValueAddress()); \
} \
@@ -877,6 +879,7 @@
CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
CASE_STATEMENT(where, how, within, CODE_SPACE) \
CASE_STATEMENT(where, how, within, CELL_SPACE) \
+ CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE) \
CASE_STATEMENT(where, how, within, MAP_SPACE) \
CASE_BODY(where, how, within, kAnyOldSpace)
@@ -1564,10 +1567,9 @@
}
-void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
- ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
- JSGlobalPropertyCell* cell =
- JSGlobalPropertyCell::cast(rinfo->target_cell());
+void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) {
+ ASSERT(rinfo->rmode() == RelocInfo::CELL);
+ Cell* cell = Cell::cast(rinfo->target_cell());
int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping);
serializer_->SerializeObject(cell, kPlain, kInnerPointer, skip);
}
diff --git a/src/serialize.h b/src/serialize.h
index 1b56a88..e5664ff 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -519,7 +519,7 @@
void VisitExternalReference(RelocInfo* rinfo);
void VisitCodeTarget(RelocInfo* target);
void VisitCodeEntry(Address entry_address);
- void VisitGlobalPropertyCell(RelocInfo* rinfo);
+ void VisitCell(RelocInfo* rinfo);
void VisitRuntimeEntry(RelocInfo* reloc);
// Used for seralizing the external strings that hold the natives source.
void VisitExternalAsciiString(
diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc
index a8806f0..576269d 100644
--- a/src/snapshot-common.cc
+++ b/src/snapshot-common.cc
@@ -45,7 +45,8 @@
OS::SNPrintF(name, "%s.size", file_name);
FILE* fp = OS::FOpen(name.start(), "r");
CHECK_NE(NULL, fp);
- int new_size, pointer_size, data_size, code_size, map_size, cell_size;
+ int new_size, pointer_size, data_size, code_size, map_size, cell_size,
+ property_cell_size;
#ifdef _MSC_VER
// Avoid warning about unsafe fscanf from MSVC.
// Please note that this is only fine if %c and %s are not being used.
@@ -57,6 +58,7 @@
CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
+ CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
#ifdef _MSC_VER
#undef fscanf
#endif
@@ -67,6 +69,8 @@
deserializer->set_reservation(CODE_SPACE, code_size);
deserializer->set_reservation(MAP_SPACE, map_size);
deserializer->set_reservation(CELL_SPACE, cell_size);
+ deserializer->set_reservation(PROPERTY_CELL_SPACE,
+ property_cell_size);
name.Dispose();
}
@@ -78,6 +82,8 @@
deserializer->set_reservation(CODE_SPACE, code_space_used_);
deserializer->set_reservation(MAP_SPACE, map_space_used_);
deserializer->set_reservation(CELL_SPACE, cell_space_used_);
+ deserializer->set_reservation(PROPERTY_CELL_SPACE,
+ property_cell_space_used_);
}
@@ -124,6 +130,8 @@
deserializer.set_reservation(CODE_SPACE, context_code_space_used_);
deserializer.set_reservation(MAP_SPACE, context_map_space_used_);
deserializer.set_reservation(CELL_SPACE, context_cell_space_used_);
+ deserializer.set_reservation(PROPERTY_CELL_SPACE,
+ context_property_cell_space_used_);
deserializer.DeserializePartial(&root);
CHECK(root->IsContext());
return Handle<Context>(Context::cast(root));
diff --git a/src/snapshot-empty.cc b/src/snapshot-empty.cc
index 70e7ab8..54236d8 100644
--- a/src/snapshot-empty.cc
+++ b/src/snapshot-empty.cc
@@ -49,6 +49,7 @@
const int Snapshot::code_space_used_ = 0;
const int Snapshot::map_space_used_ = 0;
const int Snapshot::cell_space_used_ = 0;
+const int Snapshot::property_cell_space_used_ = 0;
const int Snapshot::context_new_space_used_ = 0;
const int Snapshot::context_pointer_space_used_ = 0;
@@ -56,5 +57,6 @@
const int Snapshot::context_code_space_used_ = 0;
const int Snapshot::context_map_space_used_ = 0;
const int Snapshot::context_cell_space_used_ = 0;
+const int Snapshot::context_property_cell_space_used_ = 0;
} } // namespace v8::internal
diff --git a/src/snapshot.h b/src/snapshot.h
index c4ae45e..149306e 100644
--- a/src/snapshot.h
+++ b/src/snapshot.h
@@ -77,12 +77,14 @@
static const int code_space_used_;
static const int map_space_used_;
static const int cell_space_used_;
+ static const int property_cell_space_used_;
static const int context_new_space_used_;
static const int context_pointer_space_used_;
static const int context_data_space_used_;
static const int context_code_space_used_;
static const int context_map_space_used_;
static const int context_cell_space_used_;
+ static const int context_property_cell_space_used_;
static const int size_;
static const int raw_size_;
static const int context_size_;
diff --git a/src/spaces.cc b/src/spaces.cc
index 099ad93..8e953e2 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -72,6 +72,7 @@
owner == page->heap()->old_data_space() ||
owner == page->heap()->map_space() ||
owner == page->heap()->cell_space() ||
+ owner == page->heap()->property_cell_space() ||
owner == page->heap()->code_space());
Initialize(reinterpret_cast<PagedSpace*>(owner),
page->area_start(),
@@ -1043,6 +1044,9 @@
case CELL_SPACE:
size = 16 * kPointerSize * KB;
break;
+ case PROPERTY_CELL_SPACE:
+ size = 16 * kPointerSize * KB;
+ break;
case CODE_SPACE:
if (heap()->isolate()->code_range()->exists()) {
// When code range exists, code pages are allocated in a special way
@@ -2834,13 +2838,20 @@
// -----------------------------------------------------------------------------
-// GlobalPropertyCellSpace implementation
+// CellSpace and PropertyCellSpace implementation
// TODO(mvstanton): this is weird...the compiler can't make a vtable unless
// there is at least one non-inlined virtual function. I would prefer to hide
// the VerifyObject definition behind VERIFY_HEAP.
void CellSpace::VerifyObject(HeapObject* object) {
// The object should be a global object property cell or a free-list node.
+ CHECK(object->IsCell() ||
+ object->map() == heap()->two_pointer_filler_map());
+}
+
+
+void PropertyCellSpace::VerifyObject(HeapObject* object) {
+ // The object should be a global object property cell or a free-list node.
CHECK(object->IsJSGlobalPropertyCell() ||
object->map() == heap()->two_pointer_filler_map());
}
diff --git a/src/spaces.h b/src/spaces.h
index e7e4d52..ca61081 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -2626,12 +2626,39 @@
// -----------------------------------------------------------------------------
-// Old space for all global object property cell objects
+// Old space for simple property cell objects
class CellSpace : public FixedSpace {
public:
// Creates a property cell space object with a maximum capacity.
CellSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id)
+ : FixedSpace(heap, max_capacity, id, Cell::kSize)
+ {}
+
+ virtual int RoundSizeDownToObjectAlignment(int size) {
+ if (IsPowerOf2(Cell::kSize)) {
+ return RoundDown(size, Cell::kSize);
+ } else {
+ return (size / Cell::kSize) * Cell::kSize;
+ }
+ }
+
+ protected:
+ virtual void VerifyObject(HeapObject* obj);
+
+ public:
+ TRACK_MEMORY("CellSpace")
+};
+
+
+// -----------------------------------------------------------------------------
+// Old space for all global object property cell objects
+
+class PropertyCellSpace : public FixedSpace {
+ public:
+ // Creates a property cell space object with a maximum capacity.
+ PropertyCellSpace(Heap* heap, intptr_t max_capacity,
+ AllocationSpace id)
: FixedSpace(heap, max_capacity, id, JSGlobalPropertyCell::kSize)
{}
@@ -2647,7 +2674,7 @@
virtual void VerifyObject(HeapObject* obj);
public:
- TRACK_MEMORY("CellSpace")
+ TRACK_MEMORY("PropertyCellSpace")
};
diff --git a/src/store-buffer.cc b/src/store-buffer.cc
index c650f57..fd6366a 100644
--- a/src/store-buffer.cc
+++ b/src/store-buffer.cc
@@ -142,6 +142,11 @@
}
+bool StoreBuffer::SpaceAvailable(intptr_t space_needed) {
+ return old_limit_ - old_top_ >= space_needed;
+}
+
+
void StoreBuffer::EnsureSpace(intptr_t space_needed) {
while (old_limit_ - old_top_ < space_needed &&
old_limit_ < old_reserved_limit_) {
@@ -152,7 +157,7 @@
old_limit_ += grow;
}
- if (old_limit_ - old_top_ >= space_needed) return;
+ if (SpaceAvailable(space_needed)) return;
if (old_buffer_is_filtered_) return;
ASSERT(may_move_store_buffer_entries_);
@@ -171,9 +176,7 @@
Filter(MemoryChunk::SCAN_ON_SCAVENGE);
}
- // If filtering out the entries from scan_on_scavenge pages got us down to
- // less than half full, then we are satisfied with that.
- if (old_limit_ - old_top_ > old_top_ - old_start_) return;
+ 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.
@@ -192,7 +195,7 @@
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 (old_limit_ - old_top_ > old_top_ - old_start_) return;
+ if (SpaceAvailable(space_needed)) return;
}
UNREACHABLE();
}
@@ -294,7 +297,7 @@
void StoreBuffer::Clean() {
ClearFilteringHashSets();
Uniq(); // Also removes things that no longer point to new space.
- CheckForFullBuffer();
+ EnsureSpace(kStoreBufferSize / 2);
}
@@ -687,12 +690,6 @@
ASSERT(old_top_ <= old_limit_);
}
heap_->isolate()->counters()->store_buffer_compactions()->Increment();
- CheckForFullBuffer();
-}
-
-
-void StoreBuffer::CheckForFullBuffer() {
- EnsureSpace(kStoreBufferSize * 2);
}
} } // namespace v8::internal
diff --git a/src/store-buffer.h b/src/store-buffer.h
index 514534a..520cbc0 100644
--- a/src/store-buffer.h
+++ b/src/store-buffer.h
@@ -160,7 +160,7 @@
void ClearFilteringHashSets();
- void CheckForFullBuffer();
+ bool SpaceAvailable(intptr_t space_needed);
void Uniq();
void ExemptPopularPages(int prime_sample_step, int threshold);
@@ -223,7 +223,6 @@
~StoreBufferRebuildScope() {
store_buffer_->callback_ = stored_callback_;
store_buffer_->store_buffer_rebuilding_enabled_ = stored_state_;
- store_buffer_->CheckForFullBuffer();
}
private:
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 0f81669..40a7938 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1977,7 +1977,7 @@
Handle<Code> CallStubCompiler::CompileCustomCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> fname) {
ASSERT(HasCustomCallGenerator(function));
diff --git a/src/stub-cache.h b/src/stub-cache.h
index a1b55d8..0c756a1 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -1019,14 +1019,14 @@
// given function.
Handle<Code> CompileCustomCall(Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name);
#define DECLARE_CALL_GENERATOR(name) \
Handle<Code> Compile##name##Call(Handle<Object> object, \
Handle<JSObject> holder, \
- Handle<JSGlobalPropertyCell> cell, \
+ Handle<Cell> cell, \
Handle<JSFunction> function, \
Handle<String> fname);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
@@ -1035,7 +1035,7 @@
Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name);
@@ -1053,7 +1053,7 @@
// Generates code to load the function from the cell checking that
// it still contains the same function.
- void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
+ void GenerateLoadFunctionFromCell(Handle<Cell> cell,
Handle<JSFunction> function,
Label* miss);
diff --git a/src/type-info.cc b/src/type-info.cc
index 5113c55..32aef1c 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -42,20 +42,17 @@
namespace internal {
-TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
- TypeInfo info;
+TypeInfo TypeInfo::FromValue(Handle<Object> value) {
if (value->IsSmi()) {
- info = TypeInfo::Smi();
+ return TypeInfo::Smi();
} else if (value->IsHeapNumber()) {
- info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
+ return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
? TypeInfo::Integer32()
: TypeInfo::Double();
} else if (value->IsString()) {
- info = TypeInfo::String();
- } else {
- info = TypeInfo::Unknown();
+ return TypeInfo::String();
}
- return info;
+ return TypeInfo::Unknown();
}
@@ -80,8 +77,8 @@
int entry = dictionary_->FindEntry(IdToKey(ast_id));
if (entry != UnseededNumberDictionary::kNotFound) {
Object* value = dictionary_->ValueAt(entry);
- if (value->IsJSGlobalPropertyCell()) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(value);
+ if (value->IsCell()) {
+ Cell* cell = Cell::cast(value);
return Handle<Object>(cell->value(), isolate_);
} else {
return Handle<Object>(value, isolate_);
@@ -91,15 +88,14 @@
}
-Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetInfoCell(
+Handle<Cell> TypeFeedbackOracle::GetInfoCell(
TypeFeedbackId ast_id) {
int entry = dictionary_->FindEntry(IdToKey(ast_id));
if (entry != UnseededNumberDictionary::kNotFound) {
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
- dictionary_->ValueAt(entry));
- return Handle<JSGlobalPropertyCell>(cell, isolate_);
+ Cell* cell = Cell::cast(dictionary_->ValueAt(entry));
+ return Handle<Cell>(cell, isolate_);
}
- return Handle<JSGlobalPropertyCell>::null();
+ return Handle<Cell>::null();
}
@@ -235,24 +231,6 @@
}
-Handle<Map> TypeFeedbackOracle::CompareNilMonomorphicReceiverType(
- CompareOperation* expr) {
- Handle<Object> maybe_code = GetInfo(expr->CompareOperationFeedbackId());
- if (maybe_code->IsCode()) {
- Map* map = Handle<Code>::cast(maybe_code)->FindFirstMap();
- if (map == NULL) return Handle<Map>();
- map = map->CurrentMapForDeprecated();
- return map == NULL || CanRetainOtherContext(map, *native_context_)
- ? Handle<Map>()
- : Handle<Map>(map);
- } else if (maybe_code->IsMap()) {
- ASSERT(!Handle<Map>::cast(maybe_code)->is_deprecated());
- return Handle<Map>::cast(maybe_code);
- }
- return Handle<Map>();
-}
-
-
KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode(
TypeFeedbackId ast_id) {
Handle<Object> map_or_code = GetInfo(ast_id);
@@ -335,8 +313,7 @@
}
-Handle<JSGlobalPropertyCell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(
- CallNew* expr) {
+Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(CallNew* expr) {
return GetInfoCell(expr->CallNewFeedbackId());
}
@@ -364,69 +341,38 @@
}
-static TypeInfo TypeFromCompareType(CompareIC::State state) {
- switch (state) {
- case CompareIC::UNINITIALIZED:
- // Uninitialized means never executed.
- return TypeInfo::Uninitialized();
- case CompareIC::SMI:
- return TypeInfo::Smi();
- case CompareIC::NUMBER:
- return TypeInfo::Number();
- case CompareIC::INTERNALIZED_STRING:
- return TypeInfo::InternalizedString();
- case CompareIC::STRING:
- return TypeInfo::String();
- case CompareIC::OBJECT:
- case CompareIC::KNOWN_OBJECT:
- // TODO(kasperl): We really need a type for JS objects here.
- return TypeInfo::NonPrimitive();
- case CompareIC::GENERIC:
- default:
- return TypeInfo::Unknown();
- }
-}
+void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id,
+ Handle<Type>* left_type,
+ Handle<Type>* right_type,
+ Handle<Type>* overall_type,
+ Handle<Type>* compare_nil_type) {
+ *left_type = *right_type = *overall_type = *compare_nil_type =
+ handle(Type::Any(), isolate_);
+ Handle<Object> info = GetInfo(id);
+ if (!info->IsCode()) return;
+ Handle<Code> code = Handle<Code>::cast(info);
-
-void TypeFeedbackOracle::CompareType(CompareOperation* expr,
- TypeInfo* left_type,
- TypeInfo* right_type,
- TypeInfo* overall_type) {
- Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
- TypeInfo unknown = TypeInfo::Unknown();
- if (!object->IsCode()) {
- *left_type = *right_type = *overall_type = unknown;
- return;
- }
- Handle<Code> code = Handle<Code>::cast(object);
- if (!code->is_compare_ic_stub()) {
- *left_type = *right_type = *overall_type = unknown;
- return;
+ Handle<Map> map;
+ Map* raw_map = code->FindFirstMap();
+ if (raw_map != NULL) {
+ raw_map = raw_map->CurrentMapForDeprecated();
+ if (!CanRetainOtherContext(raw_map, *native_context_)) {
+ map = handle(raw_map, isolate_);
+ }
}
- int stub_minor_key = code->stub_info();
- CompareIC::State left_state, right_state, handler_state;
- ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
- &handler_state, NULL);
- *left_type = TypeFromCompareType(left_state);
- *right_type = TypeFromCompareType(right_state);
- *overall_type = TypeFromCompareType(handler_state);
-}
-
-
-Handle<Map> TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) {
- Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
- if (!object->IsCode()) return Handle<Map>::null();
- Handle<Code> code = Handle<Code>::cast(object);
- if (!code->is_compare_ic_stub()) return Handle<Map>::null();
- CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
- if (state != CompareIC::KNOWN_OBJECT) {
- return Handle<Map>::null();
+ if (code->is_compare_ic_stub()) {
+ int stub_minor_key = code->stub_info();
+ CompareIC::State left_state, right_state, handler_state;
+ ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
+ &handler_state, NULL);
+ *left_type = CompareIC::StateToType(isolate_, left_state);
+ *right_type = CompareIC::StateToType(isolate_, right_state);
+ *overall_type = CompareIC::StateToType(isolate_, handler_state, map);
+ } else if (code->is_compare_nil_ic_stub()) {
+ CompareNilICStub::State state(code->compare_nil_state());
+ *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map);
}
- Map* map = code->FindFirstMap()->CurrentMapForDeprecated();
- return map == NULL || CanRetainOtherContext(map, *native_context_)
- ? Handle<Map>::null()
- : Handle<Map>(map);
}
@@ -497,15 +443,15 @@
}
-TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
- Handle<Object> object = GetInfo(clause->CompareId());
- TypeInfo unknown = TypeInfo::Unknown();
- if (!object->IsCode()) return unknown;
- Handle<Code> code = Handle<Code>::cast(object);
- if (!code->is_compare_ic_stub()) return unknown;
-
- CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
- return TypeFromCompareType(state);
+Handle<Type> TypeFeedbackOracle::ClauseType(TypeFeedbackId id) {
+ Handle<Object> info = GetInfo(id);
+ Handle<Type> result(Type::None(), isolate_);
+ if (info->IsCode() && Handle<Code>::cast(info)->is_compare_ic_stub()) {
+ Handle<Code> code = Handle<Code>::cast(info);
+ CompareIC::State state = ICCompareStub::CompareState(code->stub_info());
+ result = CompareIC::StateToType(isolate_, state);
+ }
+ return result;
}
@@ -636,17 +582,6 @@
}
-byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) {
- Handle<Object> object = GetInfo(expr->CompareOperationFeedbackId());
- if (object->IsCode() &&
- Handle<Code>::cast(object)->is_compare_nil_ic_stub()) {
- return Handle<Code>::cast(object)->compare_nil_types();
- } else {
- return CompareNilICStub::Types::FullCompare().ToIntegral();
- }
-}
-
-
// Things are a bit tricky here: The iterator for the RelocInfos and the infos
// themselves are not GC-safe, so we first get all infos, then we create the
// dictionary (possibly triggering GC), and finally we relocate the collected
@@ -759,7 +694,7 @@
TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
for (int i = 0; i < cache->CellCount(); i++) {
TypeFeedbackId ast_id = cache->AstId(i);
- JSGlobalPropertyCell* cell = cache->Cell(i);
+ Cell* cell = cache->GetCell(i);
Object* value = cell->value();
if (value->IsSmi() ||
(value->IsJSFunction() &&
diff --git a/src/type-info.h b/src/type-info.h
index 53a83be..1262b31 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -30,6 +30,7 @@
#include "allocation.h"
#include "globals.h"
+#include "types.h"
#include "zone-inl.h"
namespace v8 {
@@ -113,7 +114,7 @@
return false;
}
- static TypeInfo TypeFromValue(Handle<Object> value);
+ static TypeInfo FromValue(Handle<Object> value);
bool Equals(const TypeInfo& other) {
return type_ == other.type_;
@@ -217,12 +218,12 @@
// Forward declarations.
+// TODO(rossberg): these should all go away eventually.
class Assignment;
class BinaryOperation;
class Call;
class CallNew;
class CaseClause;
-class CompareOperation;
class CompilationInfo;
class CountOperation;
class Expression;
@@ -257,7 +258,6 @@
Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
- Handle<Map> CompareNilMonomorphicReceiverType(CompareOperation* expr);
KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
@@ -283,7 +283,7 @@
CheckType GetCallCheckType(Call* expr);
Handle<JSFunction> GetCallTarget(Call* expr);
Handle<JSFunction> GetCallNewTarget(CallNew* expr);
- Handle<JSGlobalPropertyCell> GetCallNewAllocationInfoCell(CallNew* expr);
+ Handle<Cell> GetCallNewAllocationInfoCell(CallNew* expr);
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
@@ -293,12 +293,7 @@
// TODO(1571) We can't use ToBooleanStub::Types as the return value because
// of various cycles in our headers. Death to tons of implementations in
// headers!! :-P
- byte ToBooleanTypes(TypeFeedbackId ast_id);
-
- // TODO(1571) We can't use CompareNilICStub::Types as the return value because
- // of various cylces in our headers. Death to tons of implementations in
- // headers!! :-P
- byte CompareNilTypes(CompareOperation* expr);
+ byte ToBooleanTypes(TypeFeedbackId id);
// Get type information for arithmetic operations and compares.
TypeInfo UnaryType(UnaryOperation* expr);
@@ -308,12 +303,15 @@
TypeInfo* result,
bool* has_fixed_right_arg,
int* fixed_right_arg_value);
- void CompareType(CompareOperation* expr,
- TypeInfo* left_type,
- TypeInfo* right_type,
- TypeInfo* overall_type);
- Handle<Map> GetCompareMap(CompareOperation* expr);
- TypeInfo SwitchType(CaseClause* clause);
+
+ void CompareTypes(TypeFeedbackId id,
+ Handle<Type>* left_type,
+ Handle<Type>* right_type,
+ Handle<Type>* overall_type,
+ Handle<Type>* compare_nil_type);
+
+ Handle<Type> ClauseType(TypeFeedbackId id);
+
TypeInfo IncrementType(CountOperation* expr);
Zone* zone() const { return zone_; }
@@ -341,7 +339,7 @@
Handle<Object> GetInfo(TypeFeedbackId ast_id);
// Return the cell that contains type feedback.
- Handle<JSGlobalPropertyCell> GetInfoCell(TypeFeedbackId ast_id);
+ Handle<Cell> GetInfoCell(TypeFeedbackId ast_id);
private:
Handle<Context> native_context_;
diff --git a/src/types.cc b/src/types.cc
index f7fbd2d..20e8a4c 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -30,6 +30,84 @@
namespace v8 {
namespace internal {
+int Type::NumClasses() {
+ if (is_class()) {
+ return 1;
+ } else if (is_union()) {
+ Handle<Unioned> unioned = as_union();
+ int result = 0;
+ for (int i = 0; i < unioned->length(); ++i) {
+ if (union_get(unioned, i)->is_class()) ++result;
+ }
+ return result;
+ } else {
+ return 0;
+ }
+}
+
+
+int Type::NumConstants() {
+ if (is_constant()) {
+ return 1;
+ } else if (is_union()) {
+ Handle<Unioned> unioned = as_union();
+ int result = 0;
+ for (int i = 0; i < unioned->length(); ++i) {
+ if (union_get(unioned, i)->is_constant()) ++result;
+ }
+ return result;
+ } else {
+ return 0;
+ }
+}
+
+
+template<class T>
+Handle<Type> Type::Iterator<T>::get_type() {
+ ASSERT(!Done());
+ return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
+}
+
+template<>
+Handle<Map> Type::Iterator<Map>::Current() {
+ return get_type()->as_class();
+}
+
+template<>
+Handle<v8::internal::Object> Type::Iterator<v8::internal::Object>::Current() {
+ return get_type()->as_constant();
+}
+
+
+template<>
+bool Type::Iterator<Map>::matches(Handle<Type> type) {
+ return type->is_class();
+}
+
+template<>
+bool Type::Iterator<v8::internal::Object>::matches(Handle<Type> type) {
+ return type->is_constant();
+}
+
+
+template<class T>
+void Type::Iterator<T>::Advance() {
+ ++index_;
+ if (type_->is_union()) {
+ Handle<Unioned> unioned = type_->as_union();
+ for (; index_ < unioned->length(); ++index_) {
+ if (matches(union_get(unioned, index_))) return;
+ }
+ } else if (index_ == 0 && matches(type_)) {
+ return;
+ }
+ index_ = -1;
+}
+
+template class Type::Iterator<Map>;
+template class Type::Iterator<v8::internal::Object>;
+
+
// Get the smallest bitset subsuming this type.
int Type::LubBitset() {
if (this->is_bitset()) {
@@ -46,9 +124,14 @@
if (this->is_class()) {
map = *this->as_class();
} else {
- v8::internal::Object* value = this->as_constant()->value();
- if (value->IsSmi()) return kSmi;
- map = HeapObject::cast(value)->map();
+ Handle<v8::internal::Object> value = this->as_constant();
+ if (value->IsSmi()) return kInteger31;
+ map = HeapObject::cast(*value)->map();
+ if (map->instance_type() == ODDBALL_TYPE) {
+ if (value->IsUndefined()) return kUndefined;
+ if (value->IsNull()) return kNull;
+ if (value->IsTrue() || value->IsFalse()) return kBoolean;
+ }
}
switch (map->instance_type()) {
case STRING_TYPE:
@@ -56,6 +139,7 @@
case CONS_STRING_TYPE:
case CONS_ASCII_STRING_TYPE:
case SLICED_STRING_TYPE:
+ case SLICED_ASCII_STRING_TYPE:
case EXTERNAL_STRING_TYPE:
case EXTERNAL_ASCII_STRING_TYPE:
case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
@@ -92,6 +176,7 @@
case JS_TYPED_ARRAY_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_REGEXP_TYPE:
+ if (map->is_undetectable()) return kUndetectable;
return kOtherObject;
case JS_ARRAY_TYPE:
return kArray;
@@ -100,6 +185,17 @@
case JS_PROXY_TYPE:
case JS_FUNCTION_PROXY_TYPE:
return kProxy;
+ case MAP_TYPE:
+ // When compiling stub templates, the meta map is used as a place holder
+ // for the actual map with which the template is later instantiated.
+ // We treat it as a kind of type variable whose upper bound is Any.
+ // TODO(rossberg): for caching of CompareNilIC stubs to work correctly,
+ // we must exclude Undetectable here. This makes no sense, really,
+ // because it means that the template isn't actually parametric.
+ // Also, it doesn't apply elsewhere. 8-(
+ // We ought to find a cleaner solution for compiling stubs parameterised
+ // over type or class variables, esp ones with bounds...
+ return kDetectable;
default:
UNREACHABLE();
return kNone;
@@ -122,7 +218,7 @@
// Check this <= that.
-bool Type::Is(Handle<Type> that) {
+bool Type::Is(Type* that) {
// Fast path for bitsets.
if (that->is_bitset()) {
return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
@@ -132,8 +228,7 @@
return this->is_class() && *this->as_class() == *that->as_class();
}
if (that->is_constant()) {
- return this->is_constant() &&
- this->as_constant()->value() == that->as_constant()->value();
+ return this->is_constant() && *this->as_constant() == *that->as_constant();
}
// (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
@@ -163,7 +258,7 @@
// Check this overlaps that.
-bool Type::Maybe(Handle<Type> that) {
+bool Type::Maybe(Type* that) {
// Fast path for bitsets.
if (this->is_bitset()) {
return (this->as_bitset() & that->LubBitset()) != 0;
@@ -176,8 +271,7 @@
return that->is_class() && *this->as_class() == *that->as_class();
}
if (this->is_constant()) {
- return that->is_constant() &&
- this->as_constant()->value() == that->as_constant()->value();
+ return that->is_constant() && *this->as_constant() == *that->as_constant();
}
// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
diff --git a/src/types.h b/src/types.h
index 6db9bfb..883d884 100644
--- a/src/types.h
+++ b/src/types.h
@@ -48,11 +48,15 @@
// T <= Any
//
// Oddball = Boolean \/ Null \/ Undefined
-// Number = Smi \/ Double
+// Number = Integer32 \/ Double
+// Integer31 < Integer32
// Name = String \/ Symbol
// UniqueName = InternalizedString \/ Symbol
// InternalizedString < String
//
+// Allocated = Receiver \/ Number \/ Name
+// Detectable = Allocated - Undetectable
+// Undetectable < Object
// Receiver = Object \/ Proxy
// Array < Object
// Function < Object
@@ -70,8 +74,9 @@
// T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2)
// T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
//
-// Typically, the latter should be used to check whether a specific case needs
-// handling (e.g., via T->Maybe(Number)).
+// Typically, the former is to be used to select representations (e.g., via
+// T->Is(Integer31())), and the to check whether a specific case needs handling
+// (e.g., via T->Maybe(Number())).
//
// There is no functionality to discover whether a type is a leaf in the
// lattice. That is intentional. It should always be possible to refine the
@@ -89,6 +94,8 @@
public:
static Type* None() { return from_bitset(kNone); }
static Type* Any() { return from_bitset(kAny); }
+ static Type* Allocated() { return from_bitset(kAllocated); }
+ static Type* Detectable() { return from_bitset(kDetectable); }
static Type* Oddball() { return from_bitset(kOddball); }
static Type* Boolean() { return from_bitset(kBoolean); }
@@ -96,7 +103,8 @@
static Type* Undefined() { return from_bitset(kUndefined); }
static Type* Number() { return from_bitset(kNumber); }
- static Type* Smi() { return from_bitset(kSmi); }
+ static Type* Integer31() { return from_bitset(kInteger31); }
+ static Type* Integer32() { return from_bitset(kInteger32); }
static Type* Double() { return from_bitset(kDouble); }
static Type* Name() { return from_bitset(kName); }
@@ -107,6 +115,7 @@
static Type* Receiver() { return from_bitset(kReceiver); }
static Type* Object() { return from_bitset(kObject); }
+ static Type* Undetectable() { return from_bitset(kUndetectable); }
static Type* Array() { return from_bitset(kArray); }
static Type* Function() { return from_bitset(kFunction); }
static Type* Proxy() { return from_bitset(kProxy); }
@@ -122,10 +131,49 @@
static Type* Union(Handle<Type> type1, Handle<Type> type2);
static Type* Optional(Handle<Type> type); // type \/ Undefined
- bool Is(Handle<Type> that);
- bool Maybe(Handle<Type> that);
+ bool Is(Type* that);
+ bool Is(Handle<Type> that) { return this->Is(*that); }
+ bool Maybe(Type* that);
+ bool Maybe(Handle<Type> that) { return this->Maybe(*that); }
- // TODO(rossberg): method to iterate unions?
+ bool IsClass() { return is_class(); }
+ bool IsConstant() { return is_constant(); }
+ Handle<Map> AsClass() { return as_class(); }
+ Handle<v8::internal::Object> AsConstant() { return as_constant(); }
+
+ int NumClasses();
+ int NumConstants();
+
+ template<class T>
+ class Iterator {
+ public:
+ bool Done() const { return index_ < 0; }
+ Handle<T> Current();
+ void Advance();
+
+ private:
+ friend class Type;
+
+ Iterator() : index_(-1) {}
+ explicit Iterator(Handle<Type> type) : type_(type), index_(-1) {
+ Advance();
+ }
+
+ inline bool matches(Handle<Type> type);
+ inline Handle<Type> get_type();
+
+ Handle<Type> type_;
+ int index_;
+ };
+
+ Iterator<Map> Classes() {
+ if (this->is_bitset()) return Iterator<Map>();
+ return Iterator<Map>(this->handle());
+ }
+ Iterator<v8::internal::Object> Constants() {
+ if (this->is_bitset()) return Iterator<v8::internal::Object>();
+ return Iterator<v8::internal::Object>(this->handle());
+ }
private:
// A union is a fixed array containing types. Invariants:
@@ -138,24 +186,29 @@
kNull = 1 << 0,
kUndefined = 1 << 1,
kBoolean = 1 << 2,
- kSmi = 1 << 3,
- kDouble = 1 << 4,
- kSymbol = 1 << 5,
- kInternalizedString = 1 << 6,
- kOtherString = 1 << 7,
- kArray = 1 << 8,
- kFunction = 1 << 9,
- kOtherObject = 1 << 10,
- kProxy = 1 << 11,
+ kInteger31 = 1 << 3,
+ kOtherInteger = 1 << 4,
+ kDouble = 1 << 5,
+ kSymbol = 1 << 6,
+ kInternalizedString = 1 << 7,
+ kOtherString = 1 << 8,
+ kUndetectable = 1 << 9,
+ kArray = 1 << 10,
+ kFunction = 1 << 11,
+ kOtherObject = 1 << 12,
+ kProxy = 1 << 13,
kOddball = kBoolean | kNull | kUndefined,
- kNumber = kSmi | kDouble,
+ kInteger32 = kInteger31 | kOtherInteger,
+ kNumber = kInteger32 | kDouble,
kString = kInternalizedString | kOtherString,
kUniqueName = kSymbol | kInternalizedString,
kName = kSymbol | kString,
- kObject = kArray | kFunction | kOtherObject,
+ kObject = kUndetectable | kArray | kFunction | kOtherObject,
kReceiver = kObject | kProxy,
- kAny = kOddball | kNumber | kName | kReceiver,
+ kAllocated = kDouble | kName | kReceiver,
+ kAny = kOddball | kNumber | kAllocated,
+ kDetectable = kAllocated - kUndetectable,
kNone = 0
};
@@ -166,7 +219,10 @@
int as_bitset() { return Smi::cast(this)->value(); }
Handle<Map> as_class() { return Handle<Map>::cast(handle()); }
- Handle<Box> as_constant() { return Handle<Box>::cast(handle()); }
+ Handle<v8::internal::Object> as_constant() {
+ Handle<Box> box = Handle<Box>::cast(handle());
+ return v8::internal::handle(box->value(), box->GetIsolate());
+ }
Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); }
Handle<Type> handle() { return handle_via_isolate_of(this); }
diff --git a/src/typing.cc b/src/typing.cc
index 4ba6721..e1fd8aa 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -52,7 +52,7 @@
} while (false)
-void AstTyper::Type(CompilationInfo* info) {
+void AstTyper::Run(CompilationInfo* info) {
AstTyper* visitor = new(info->zone()) AstTyper(info);
Scope* scope = info->scope();
diff --git a/src/typing.h b/src/typing.h
index d8708c2..1f172ea 100644
--- a/src/typing.h
+++ b/src/typing.h
@@ -43,7 +43,7 @@
class AstTyper: public AstVisitor {
public:
- static void Type(CompilationInfo* info);
+ static void Run(CompilationInfo* info);
void* operator new(size_t size, Zone* zone) {
return zone->New(static_cast<int>(size));
diff --git a/src/v8-counters.h b/src/v8-counters.h
index c810cba..373618e 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -63,12 +63,16 @@
V8.MemoryExternalFragmentationMapSpace) \
HP(external_fragmentation_cell_space, \
V8.MemoryExternalFragmentationCellSpace) \
+ HP(external_fragmentation_property_cell_space, \
+ V8.MemoryExternalFragmentationPropertyCellSpace) \
HP(external_fragmentation_lo_space, \
V8.MemoryExternalFragmentationLoSpace) \
HP(heap_fraction_map_space, \
V8.MemoryHeapFractionMapSpace) \
HP(heap_fraction_cell_space, \
V8.MemoryHeapFractionCellSpace) \
+ HP(heap_fraction_property_cell_space, \
+ V8.MemoryHeapFractionPropertyCellSpace) \
#define HISTOGRAM_MEMORY_LIST(HM) \
@@ -77,7 +81,9 @@
HM(heap_sample_map_space_committed, \
V8.MemoryHeapSampleMapSpaceCommitted) \
HM(heap_sample_cell_space_committed, \
- V8.MemoryHeapSampleCellSpaceCommitted)
+ V8.MemoryHeapSampleCellSpaceCommitted) \
+ HM(heap_sample_property_cell_space_committed, \
+ V8.MemoryHeapSamplePropertyCellSpaceCommitted) \
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
@@ -297,6 +303,12 @@
SC(cell_space_bytes_available, V8.MemoryCellSpaceBytesAvailable) \
SC(cell_space_bytes_committed, V8.MemoryCellSpaceBytesCommitted) \
SC(cell_space_bytes_used, V8.MemoryCellSpaceBytesUsed) \
+ SC(property_cell_space_bytes_available, \
+ V8.MemoryPropertyCellSpaceBytesAvailable) \
+ SC(property_cell_space_bytes_committed, \
+ V8.MemoryPropertyCellSpaceBytesCommitted) \
+ SC(property_cell_space_bytes_used, \
+ V8.MemoryPropertyCellSpaceBytesUsed) \
SC(lo_space_bytes_available, V8.MemoryLoSpaceBytesAvailable) \
SC(lo_space_bytes_committed, V8.MemoryLoSpaceBytesCommitted) \
SC(lo_space_bytes_used, V8.MemoryLoSpaceBytesUsed)
diff --git a/src/v8globals.h b/src/v8globals.h
index 98940c5..4932da9 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -180,12 +180,13 @@
CODE_SPACE, // No pointers to new space, marked executable.
MAP_SPACE, // Only and all map objects.
CELL_SPACE, // Only and all cell objects.
+ PROPERTY_CELL_SPACE, // Only and all global property cell objects.
LO_SPACE, // Promoted large objects.
FIRST_SPACE = NEW_SPACE,
LAST_SPACE = LO_SPACE,
FIRST_PAGED_SPACE = OLD_POINTER_SPACE,
- LAST_PAGED_SPACE = CELL_SPACE
+ LAST_PAGED_SPACE = PROPERTY_CELL_SPACE
};
const int kSpaceTagSize = 3;
const int kSpaceTagMask = (1 << kSpaceTagSize) - 1;
diff --git a/src/v8natives.js b/src/v8natives.js
index e168b71..76eeac6 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1786,30 +1786,36 @@
}
-function NewFunction(arg1) { // length == 1
- var n = %_ArgumentsLength();
+function NewFunctionString(arguments, function_token) {
+ var n = arguments.length;
var p = '';
if (n > 1) {
- p = new InternalArray(n - 1);
- for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
- p = Join(p, n - 1, ',', NonStringToString);
+ p = ToString(arguments[0]);
+ for (var i = 1; i < n - 1; i++) {
+ p += ',' + ToString(arguments[i]);
+ }
// If the formal parameters string include ) - an illegal
// character - it may make the combined function expression
// compile. We avoid this problem by checking for this early on.
if (%_CallFunction(p, ')', StringIndexOf) != -1) {
- throw MakeSyntaxError('paren_in_arg_string',[]);
+ throw MakeSyntaxError('paren_in_arg_string', []);
}
// If the formal parameters include an unbalanced block comment, the
// function must be rejected. Since JavaScript does not allow nested
// comments we can include a trailing block comment to catch this.
p += '\n/' + '**/';
}
- var body = (n > 0) ? ToString(%_Arguments(n - 1)) : '';
- var source = '(function(' + p + ') {\n' + body + '\n})';
+ var body = (n > 0) ? ToString(arguments[n - 1]) : '';
+ return '(' + function_token + '(' + p + ') {\n' + body + '\n})';
+}
+
+function FunctionConstructor(arg1) { // length == 1
+ var source = NewFunctionString(arguments, 'function');
var global_receiver = %GlobalReceiver(global);
+ // Compile the string in the constructor and not a helper so that errors
+ // appear to come from here.
var f = %_CallFunction(global_receiver, %CompileString(source, true));
-
%FunctionMarkNameShouldPrintAsAnonymous(f);
return f;
}
@@ -1820,7 +1826,7 @@
function SetUpFunction() {
%CheckIsBootstrapping();
- %SetCode($Function, NewFunction);
+ %SetCode($Function, FunctionConstructor);
%SetProperty($Function.prototype, "constructor", $Function, DONT_ENUM);
InstallFunctions($Function.prototype, DONT_ENUM, $Array(
diff --git a/src/version.cc b/src/version.cc
index c07f9be..f6e8e2f 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 19
-#define BUILD_NUMBER 13
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 14
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 91bc528..d1d6278 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -332,24 +332,22 @@
}
-Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
+Handle<Cell> RelocInfo::target_cell_handle() {
+ ASSERT(rmode_ == RelocInfo::CELL);
Address address = Memory::Address_at(pc_);
- return Handle<JSGlobalPropertyCell>(
- reinterpret_cast<JSGlobalPropertyCell**>(address));
+ return Handle<Cell>(reinterpret_cast<Cell**>(address));
}
-JSGlobalPropertyCell* RelocInfo::target_cell() {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- return JSGlobalPropertyCell::FromValueAddress(Memory::Address_at(pc_));
+Cell* RelocInfo::target_cell() {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ return Cell::FromValueAddress(Memory::Address_at(pc_));
}
-void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
- WriteBarrierMode mode) {
- ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
- Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
+void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+ ASSERT(rmode_ == RelocInfo::CELL);
+ Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
CPU::FlushICache(pc_, sizeof(Address));
if (mode == UPDATE_WRITE_BARRIER &&
@@ -445,8 +443,8 @@
CPU::FlushICache(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
visitor->VisitCodeTarget(this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- visitor->VisitGlobalPropertyCell(this);
+ } else if (mode == RelocInfo::CELL) {
+ visitor->VisitCell(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
visitor->VisitExternalReference(this);
CPU::FlushICache(pc_, sizeof(Address));
@@ -475,8 +473,8 @@
CPU::FlushICache(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(heap, this);
- } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
- StaticVisitor::VisitGlobalPropertyCell(heap, this);
+ } else if (mode == RelocInfo::CELL) {
+ StaticVisitor::VisitCell(heap, this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(this);
CPU::FlushICache(pc_, sizeof(Address));
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index bc2e59a..40025d3 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -3727,7 +3727,7 @@
Label initialize, done;
// Load the cache state into rcx.
- __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+ __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
// A monomorphic cache hit or an already megamorphic state: invoke the
// function without changing the state.
@@ -3742,13 +3742,13 @@
__ j(equal, &initialize, Label::kNear);
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
- __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
TypeFeedbackCells::MegamorphicSentinel(isolate));
__ jmp(&done, Label::kNear);
// An uninitialized cache is patched with the function.
__ bind(&initialize);
- __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi);
+ __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi);
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -3766,7 +3766,7 @@
Label initialize, done, miss, megamorphic, not_array_function;
// Load the cache state into rcx.
- __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+ __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
// A monomorphic cache hit or an already megamorphic state: invoke the
// function without changing the state.
@@ -3799,7 +3799,7 @@
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
__ bind(&megamorphic);
- __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
TypeFeedbackCells::MegamorphicSentinel(isolate));
__ jmp(&done, Label::kNear);
@@ -3817,12 +3817,12 @@
Handle<Object> initial_kind_sentinel =
TypeFeedbackCells::MonomorphicArraySentinel(isolate,
GetInitialFastElementsKind());
- __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
initial_kind_sentinel);
__ jmp(&done);
__ bind(¬_array_function);
- __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi);
+ __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi);
// No need for a write barrier here - cells are rescanned.
__ bind(&done);
@@ -3893,7 +3893,7 @@
// If there is a call target cache, mark it megamorphic in the
// non-function case. MegamorphicSentinel is an immortal immovable
// object (undefined) so no write barrier is needed.
- __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
TypeFeedbackCells::MegamorphicSentinel(isolate));
}
// Check for function proxy.
@@ -6934,13 +6934,12 @@
__ CmpObjectType(rcx, MAP_TYPE, rcx);
__ Check(equal, "Unexpected initial map for Array function");
- // We should either have undefined in ebx or a valid jsglobalpropertycell
+ // We should either have undefined in ebx or a valid cell
Label okay_here;
- Handle<Map> global_property_cell_map(
- masm->isolate()->heap()->global_property_cell_map());
+ Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
__ Cmp(rbx, undefined_sentinel);
__ j(equal, &okay_here);
- __ Cmp(FieldOperand(rbx, 0), global_property_cell_map);
+ __ Cmp(FieldOperand(rbx, 0), cell_map);
__ Assert(equal, "Expected property cell in register rbx");
__ bind(&okay_here);
}
@@ -6950,7 +6949,7 @@
// Get the elements kind and case on that.
__ Cmp(rbx, undefined_sentinel);
__ j(equal, &no_info);
- __ movq(rdx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));
+ __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset));
__ JumpIfNotSmi(rdx, &no_info);
__ SmiToInteger32(rdx, rdx);
__ jmp(&switch_ready);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index e9fe2a8..74ccef9 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -118,7 +118,7 @@
CompilationInfo* info = info_;
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
- profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
+ profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
@@ -308,7 +308,7 @@
void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
__ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
- __ SmiAddConstant(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
Smi::FromInt(-delta));
}
@@ -323,8 +323,7 @@
__ movq(kScratchRegister,
reinterpret_cast<uint64_t>(Smi::FromInt(reset_value)),
RelocInfo::NONE64);
- __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
- kScratchRegister);
+ __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
}
@@ -1128,14 +1127,12 @@
Label non_proxy;
__ bind(&fixed_array);
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(
- Handle<Object>(
- Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
- isolate()));
+ Handle<Cell> cell = isolate()->factory()->NewCell(
+ Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+ isolate()));
RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
__ LoadHeapObject(rbx, cell);
- __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
__ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
@@ -1974,8 +1971,12 @@
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::INITIAL:
- case Yield::SUSPEND: {
+ case Yield::SUSPEND:
+ // Pop value from top-of-stack slot; box result into result register.
+ EmitCreateIteratorResult(false);
+ __ push(result_register());
+ // Fall through.
+ case Yield::INITIAL: {
VisitForStackValue(expr->generator_object());
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ movq(context_register(),
@@ -1984,12 +1985,8 @@
Label resume;
__ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
__ j(not_equal, &resume);
- if (expr->yield_kind() == Yield::SUSPEND) {
- EmitReturnIteratorResult(false);
- } else {
- __ pop(result_register());
- EmitReturnSequence();
- }
+ __ pop(result_register());
+ EmitReturnSequence();
__ bind(&resume);
context()->Plug(result_register());
@@ -2001,7 +1998,10 @@
__ Move(FieldOperand(result_register(),
JSGeneratorObject::kContinuationOffset),
Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
- EmitReturnIteratorResult(true);
+ // Pop value from top-of-stack slot, box result into result register.
+ EmitCreateIteratorResult(true);
+ EmitUnwindBeforeReturn();
+ EmitReturnSequence();
break;
}
@@ -2031,17 +2031,18 @@
// try { received = yield result.value }
__ bind(&l_try);
- __ pop(rax); // result.value
+ EmitCreateIteratorResult(false); // pop and box to rax
__ PushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(rax); // result.value
+ __ push(rax); // result
__ push(Operand(rsp, (0 + 1) * kPointerSize + handler_size)); // g
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ movq(context_register(),
Operand(rbp, StandardFrameConstants::kContextOffset));
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &l_resume);
- EmitReturnIteratorResult(false);
+ __ pop(rax); // result
+ EmitReturnSequence();
__ bind(&l_resume); // received in rax
__ PopTryHandler();
@@ -2195,13 +2196,20 @@
}
-void FullCodeGenerator::EmitReturnIteratorResult(bool done) {
+void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Label gc_required;
Label allocated;
Handle<Map> map(isolate()->native_context()->generator_result_map());
__ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
+ __ jmp(&allocated);
+
+ __ bind(&gc_required);
+ __ Push(Smi::FromInt(map->instance_size()));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
+ __ movq(context_register(),
+ Operand(rbp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ Move(rbx, map);
@@ -2222,26 +2230,6 @@
// root set.
__ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
rcx, rdx, kDontSaveFPRegs);
-
- if (done) {
- // Exit all nested statements.
- NestedStatement* current = nesting_stack_;
- int stack_depth = 0;
- int context_length = 0;
- while (current != NULL) {
- current = current->Exit(&stack_depth, &context_length);
- }
- __ Drop(stack_depth);
- }
-
- EmitReturnSequence();
-
- __ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
- __ movq(context_register(),
- Operand(rbp, StandardFrameConstants::kContextOffset));
- __ jmp(&allocated);
}
@@ -2620,8 +2608,7 @@
flags = static_cast<CallFunctionFlags>(flags | RECORD_CALL_TARGET);
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
__ Move(rbx, cell);
@@ -2804,8 +2791,7 @@
// Record call targets in unoptimized code, but not in the snapshot.
Handle<Object> uninitialized =
TypeFeedbackCells::UninitializedSentinel(isolate());
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(uninitialized);
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
__ Move(rbx, cell);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index f423133..1dd27ac 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -92,20 +92,7 @@
RegisterDependentCodeForEmbeddedMaps(code);
}
PopulateDeoptimizationData(code);
- for (int i = 0 ; i < prototype_maps_.length(); i++) {
- prototype_maps_.at(i)->AddDependentCode(
- DependentCode::kPrototypeCheckGroup, code);
- }
- for (int i = 0 ; i < transition_maps_.length(); i++) {
- transition_maps_.at(i)->AddDependentCode(
- DependentCode::kTransitionGroup, code);
- }
- if (graph()->depends_on_empty_array_proto_elements()) {
- isolate()->initial_object_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- isolate()->initial_array_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- }
+ info()->CommitDependentMaps(code);
}
@@ -482,27 +469,15 @@
void LCodeGen::WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* pushed_arguments_index,
- int* pushed_arguments_count) {
+ Translation* translation) {
if (environment == NULL) return;
// The translation includes one command per value in the environment.
- int translation_size = environment->values()->length();
+ int translation_size = environment->translation_size();
// The output frame height does not include the parameters.
int height = translation_size - environment->parameter_count();
- // Function parameters are arguments to the outermost environment. The
- // arguments index points to the first element of a sequence of tagged
- // values on the stack that represent the arguments. This needs to be
- // kept in sync with the LArgumentsElements implementation.
- *pushed_arguments_index = -environment->parameter_count();
- *pushed_arguments_count = environment->parameter_count();
-
- WriteTranslation(environment->outer(),
- translation,
- pushed_arguments_index,
- pushed_arguments_count);
+ WriteTranslation(environment->outer(), translation);
bool has_closure_id = !info()->closure().is_null() &&
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
@@ -534,23 +509,6 @@
break;
}
- // Inlined frames which push their arguments cause the index to be
- // bumped and another stack area to be used for materialization,
- // otherwise actual argument values are unknown for inlined frames.
- bool arguments_known = true;
- int arguments_index = *pushed_arguments_index;
- int arguments_count = *pushed_arguments_count;
- if (environment->entry() != NULL) {
- arguments_known = environment->entry()->arguments_pushed();
- arguments_index = arguments_index < 0
- ? GetStackSlotCount() : arguments_index + arguments_count;
- arguments_count = environment->entry()->arguments_count() + 1;
- if (environment->entry()->arguments_pushed()) {
- *pushed_arguments_index = arguments_index;
- *pushed_arguments_count = arguments_count;
- }
- }
-
for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either
@@ -562,10 +520,7 @@
AddToTranslation(translation,
environment->spilled_registers()[value->index()],
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
} else if (
value->IsDoubleRegister() &&
environment->spilled_double_registers()[value->index()] != NULL) {
@@ -574,20 +529,36 @@
translation,
environment->spilled_double_registers()[value->index()],
false,
- false,
- arguments_known,
- arguments_index,
- arguments_count);
+ false);
}
}
+ // TODO(mstarzinger): Introduce marker operands to indicate that this value
+ // is not present and must be reconstructed from the deoptimizer. Currently
+ // this is only used for the arguments object.
+ if (value == NULL) {
+ int arguments_count = environment->values()->length() - translation_size;
+ translation->BeginArgumentsObject(arguments_count);
+ for (int i = 0; i < arguments_count; ++i) {
+ LOperand* value = environment->values()->at(translation_size + i);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsRegister() ||
+ environment->spilled_registers()[value->index()] == NULL);
+ ASSERT(environment->spilled_registers() == NULL ||
+ !value->IsDoubleRegister() ||
+ environment->spilled_double_registers()[value->index()] == NULL);
+ AddToTranslation(translation,
+ value,
+ environment->HasTaggedValueAt(translation_size + i),
+ environment->HasUint32ValueAt(translation_size + i));
+ }
+ continue;
+ }
+
AddToTranslation(translation,
value,
environment->HasTaggedValueAt(i),
- environment->HasUint32ValueAt(i),
- arguments_known,
- arguments_index,
- arguments_count);
+ environment->HasUint32ValueAt(i));
}
}
@@ -595,17 +566,8 @@
void LCodeGen::AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count) {
- if (op == NULL) {
- // TODO(twuerthinger): Introduce marker operands to indicate that this value
- // is not present and must be reconstructed from the deoptimizer. Currently
- // this is only used for the arguments object.
- translation->StoreArgumentsObject(
- arguments_known, arguments_index, arguments_count);
- } else if (op->IsStackSlot()) {
+ bool is_uint32) {
+ if (op->IsStackSlot()) {
if (is_tagged) {
translation->StoreStackSlot(op->index());
} else if (is_uint32) {
@@ -710,8 +672,6 @@
int frame_count = 0;
int jsframe_count = 0;
- int args_index = 0;
- int args_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count;
if (e->frame_type() == JS_FUNCTION) {
@@ -719,7 +679,7 @@
}
}
Translation translation(&translations_, frame_count, jsframe_count, zone());
- WriteTranslation(environment, &translation, &args_index, &args_count);
+ WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset();
environment->Register(deoptimization_index,
@@ -2490,9 +2450,8 @@
Register map = ToRegister(instr->temp());
__ movq(map, FieldOperand(object, HeapObject::kMapOffset));
__ bind(deferred->map_check()); // Label for calculating code patching.
- Handle<JSGlobalPropertyCell> cache_cell =
- factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
- __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
+ __ movq(kScratchRegister, cache_cell, RelocInfo::CELL);
__ cmpq(map, Operand(kScratchRegister, 0));
__ j(not_equal, &cache_miss, Label::kNear);
// Patched to load either true or false.
@@ -2661,7 +2620,7 @@
void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
Register value = ToRegister(instr->value());
- Handle<JSGlobalPropertyCell> cell_handle = instr->hydrogen()->cell();
+ Handle<Cell> cell_handle = instr->hydrogen()->cell();
// If the cell we are storing to contains the hole it could have
// been deleted from the property dictionary. In that case, we need
@@ -2671,14 +2630,14 @@
// We have a temp because CompareRoot might clobber kScratchRegister.
Register cell = ToRegister(instr->temp());
ASSERT(!value.is(cell));
- __ movq(cell, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
+ __ movq(cell, cell_handle, RelocInfo::CELL);
__ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr->environment());
// Store the value.
__ movq(Operand(cell, 0), value);
} else {
// Store the value.
- __ movq(kScratchRegister, cell_handle, RelocInfo::GLOBAL_PROPERTY_CELL);
+ __ movq(kScratchRegister, cell_handle, RelocInfo::CELL);
__ movq(Operand(kScratchRegister, 0), value);
}
// Cells are always rescanned, so no write barrier here.
@@ -3964,8 +3923,26 @@
ArrayNoArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
} else if (instr->arity() == 1) {
+ Label done;
+ if (IsFastPackedElementsKind(kind)) {
+ Label packed_case;
+ // We might need a change here
+ // look at the first argument
+ __ movq(rcx, Operand(rsp, 0));
+ __ testq(rcx, rcx);
+ __ j(zero, &packed_case);
+
+ ElementsKind holey_kind = GetHoleyElementsKind(kind);
+ ArraySingleArgumentConstructorStub stub(holey_kind,
+ disable_allocation_sites);
+ CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ jmp(&done);
+ __ bind(&packed_case);
+ }
+
ArraySingleArgumentConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
+ __ bind(&done);
} else {
ArrayNArgumentsConstructorStub stub(kind, disable_allocation_sites);
CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
@@ -4025,9 +4002,6 @@
}
if (!transition.is_null()) {
- if (transition->CanBeDeprecated()) {
- transition_maps_.Add(transition, info()->zone());
- }
if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
__ Move(FieldOperand(object, HeapObject::kMapOffset), transition);
} else {
@@ -5100,11 +5074,7 @@
ASSERT(prototypes->length() == maps->length());
- if (instr->hydrogen()->CanOmitPrototypeChecks()) {
- for (int i = 0; i < maps->length(); i++) {
- prototype_maps_.Add(maps->at(i), info()->zone());
- }
- } else {
+ if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
for (int i = 0; i < prototypes->length(); i++) {
__ LoadHeapObject(reg, prototypes->at(i));
DoCheckMapCommon(reg, maps->at(i), instr);
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 07a948c..31dd9c4 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -57,8 +57,6 @@
deoptimizations_(4, info->zone()),
jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
- prototype_maps_(0, info->zone()),
- transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -141,10 +139,7 @@
void DoGap(LGap* instr);
// Emit frame translation commands for an environment.
- void WriteTranslation(LEnvironment* environment,
- Translation* translation,
- int* arguments_index,
- int* arguments_count);
+ void WriteTranslation(LEnvironment* environment, Translation* translation);
// Declare methods that deal with the individual node types.
#define DECLARE_DO(type) void Do##type(L##type* node);
@@ -255,10 +250,7 @@
void AddToTranslation(Translation* translation,
LOperand* op,
bool is_tagged,
- bool is_uint32,
- bool arguments_known,
- int arguments_index,
- int arguments_count);
+ bool is_uint32);
void RegisterDependentCodeForEmbeddedMaps(Handle<Code> code);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
@@ -362,8 +354,6 @@
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<Deoptimizer::JumpTableEntry> jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
- ZoneList<Handle<Map> > prototype_maps_;
- ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index cb0659d..57a8b2e 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -937,7 +937,7 @@
BailoutId ast_id = hydrogen_env->ast_id();
ASSERT(!ast_id.IsNone() ||
hydrogen_env->frame_type() != JS_FUNCTION);
- int value_count = hydrogen_env->length();
+ int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
LEnvironment* result = new(zone()) LEnvironment(
hydrogen_env->closure(),
hydrogen_env->frame_type(),
@@ -948,13 +948,15 @@
outer,
hydrogen_env->entry(),
zone());
+ bool needs_arguments_object_materialization = false;
int argument_index = *argument_index_accumulator;
- for (int i = 0; i < value_count; ++i) {
+ for (int i = 0; i < hydrogen_env->length(); ++i) {
if (hydrogen_env->is_special_index(i)) continue;
HValue* value = hydrogen_env->values()->at(i);
LOperand* op = NULL;
if (value->IsArgumentsObject()) {
+ needs_arguments_object_materialization = true;
op = NULL;
} else if (value->IsPushArgument()) {
op = new(zone()) LArgument(argument_index++);
@@ -966,6 +968,22 @@
value->CheckFlag(HInstruction::kUint32));
}
+ if (needs_arguments_object_materialization) {
+ HArgumentsObject* arguments = hydrogen_env->entry() == NULL
+ ? graph()->GetArgumentsObject()
+ : hydrogen_env->entry()->arguments_object();
+ ASSERT(arguments->IsLinked());
+ for (int i = 1; i < arguments->arguments_count(); ++i) {
+ HValue* value = arguments->arguments_values()->at(i);
+ ASSERT(!value->IsArgumentsObject() && !value->IsPushArgument());
+ ASSERT(HInstruction::cast(value)->IsLinked());
+ LOperand* op = UseAny(value);
+ result->AddValue(op,
+ value->representation(),
+ value->CheckFlag(HInstruction::kUint32));
+ }
+ }
+
if (hydrogen_env->frame_type() == JS_FUNCTION) {
*argument_index_accumulator = argument_index;
}
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 46e2c69..a2568a4 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -2357,9 +2357,8 @@
Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ movq(result, cell, RelocInfo::CELL);
movq(result, Operand(result, 0));
} else {
Move(result, object);
@@ -2370,9 +2369,8 @@
void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ movq(kScratchRegister, cell, RelocInfo::CELL);
cmpq(reg, Operand(kScratchRegister, 0));
} else {
Cmp(reg, object);
@@ -2383,9 +2381,8 @@
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
- Handle<JSGlobalPropertyCell> cell =
- isolate()->factory()->NewJSGlobalPropertyCell(object);
- movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ Handle<Cell> cell = isolate()->factory()->NewCell(object);
+ movq(kScratchRegister, cell, RelocInfo::CELL);
movq(kScratchRegister, Operand(kScratchRegister, 0));
push(kScratchRegister);
} else {
@@ -2394,13 +2391,12 @@
}
-void MacroAssembler::LoadGlobalCell(Register dst,
- Handle<JSGlobalPropertyCell> cell) {
+void MacroAssembler::LoadGlobalCell(Register dst, Handle<Cell> cell) {
if (dst.is(rax)) {
AllowDeferredHandleDereference embedding_raw_address;
- load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL);
+ load_rax(cell.location(), RelocInfo::CELL);
} else {
- movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ movq(dst, cell, RelocInfo::CELL);
movq(dst, Operand(dst, 0));
}
}
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index c10cbc6..7b8747c 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -810,7 +810,7 @@
}
// Load a global cell into a register.
- void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell);
+ void LoadGlobalCell(Register dst, Handle<Cell> cell);
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the rsp register.
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 06d8f71..c105905 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -741,7 +741,7 @@
GlobalObject::EnsurePropertyCell(global, name);
ASSERT(cell->value()->IsTheHole());
__ Move(scratch, cell);
- __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+ __ Cmp(FieldOperand(scratch, Cell::kValueOffset),
masm->isolate()->factory()->the_hole_value());
__ j(not_equal, miss);
}
@@ -1485,12 +1485,12 @@
void CallStubCompiler::GenerateLoadFunctionFromCell(
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Label* miss) {
// Get the value from the cell.
__ Move(rdi, cell);
- __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
+ __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset));
// Check that the cell contains the same function.
if (heap()->InNewSpace(*function)) {
@@ -1584,7 +1584,7 @@
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1834,7 +1834,7 @@
Handle<Code> CallStubCompiler::CompileArrayPopCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1915,7 +1915,7 @@
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -1995,7 +1995,7 @@
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2075,7 +2075,7 @@
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2146,7 +2146,7 @@
Handle<Code> CallStubCompiler::CompileMathFloorCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// TODO(872): implement this.
@@ -2157,7 +2157,7 @@
Handle<Code> CallStubCompiler::CompileMathAbsCall(
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
// ----------- S t a t e -------------
@@ -2263,7 +2263,7 @@
const CallOptimization& optimization,
Handle<Object> object,
Handle<JSObject> holder,
- Handle<JSGlobalPropertyCell> cell,
+ Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
ASSERT(optimization.is_simple_api_call());
diff --git a/test/cctest/test-compare-nil-ic-stub.cc b/test/cctest/test-compare-nil-ic-stub.cc
index affb8bd..258ab01 100644
--- a/test/cctest/test-compare-nil-ic-stub.cc
+++ b/test/cctest/test-compare-nil-ic-stub.cc
@@ -34,26 +34,26 @@
using namespace v8::internal;
-#define Types CompareNilICStub::Types
+typedef CompareNilICStub::State State;
-TEST(TypeConstructors) {
- Types types;
- types.Add(CompareNilICStub::MONOMORPHIC_MAP);
- Types types2(types);
- CHECK_EQ(types.ToIntegral(), types2.ToIntegral());
+TEST(StateConstructors) {
+ State state;
+ state.Add(CompareNilICStub::MONOMORPHIC_MAP);
+ State state2(state);
+ CHECK_EQ(state.ToIntegral(), state2.ToIntegral());
}
TEST(ExternalICStateParsing) {
- Types types;
- types.Add(CompareNilICStub::UNDEFINED);
- CompareNilICStub stub(kUndefinedValue, types);
+ State state;
+ state.Add(CompareNilICStub::UNDEFINED);
+ CompareNilICStub stub(kUndefinedValue, state);
CompareNilICStub stub2(stub.GetExtraICState());
CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue());
- CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral());
+ CHECK_EQ(stub.GetState().ToIntegral(), stub2.GetState().ToIntegral());
}
-TEST(SettingTypes) {
- Types state;
+TEST(SettingState) {
+ State state;
CHECK(state.IsEmpty());
state.Add(CompareNilICStub::NULL_TYPE);
CHECK(!state.IsEmpty());
@@ -66,20 +66,22 @@
CHECK(!state.Contains(CompareNilICStub::UNDETECTABLE));
}
-TEST(ClearTypes) {
- Types state;
+TEST(ClearState) {
+ State state;
state.Add(CompareNilICStub::NULL_TYPE);
state.RemoveAll();
CHECK(state.IsEmpty());
}
-TEST(FullCompare) {
- Types state;
- CHECK(Types::FullCompare() != state);
+TEST(Generic) {
+ State state;
+ CHECK(State::Generic() != state);
state.Add(CompareNilICStub::UNDEFINED);
- CHECK(state != Types::FullCompare());
+ CHECK(state != State::Generic());
state.Add(CompareNilICStub::NULL_TYPE);
- CHECK(state != Types::FullCompare());
+ CHECK(state != State::Generic());
state.Add(CompareNilICStub::UNDETECTABLE);
- CHECK(state == Types::FullCompare());
+ CHECK(state != State::Generic());
+ state.Add(CompareNilICStub::GENERIC);
+ CHECK(state == State::Generic());
}
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index a615fe9..95930b4 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -917,3 +917,89 @@
cpu_profiler->DeleteAllCpuProfiles();
}
+
+
+static const char* cpu_profiler_sourceURL_source =
+"function start(timeout) {\n"
+" var start = Date.now();\n"
+" var duration = 0;\n"
+" do {\n"
+" try {\n"
+" duration = Date.now() - start;\n"
+" } catch(e) { }\n"
+" } while (duration < timeout);\n"
+" return duration;\n"
+"}\n"
+"//# sourceURL=cpu_profiler_sourceURL_source.js";
+
+
+TEST(SourceURLSupportForNewFunctions) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::New(cpu_profiler_sourceURL_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("start")));
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ int32_t profiling_interval_ms = 200;
+#if defined(_WIN32) || defined(_WIN64)
+ // 200ms is not enough on Windows. See
+ // https://code.google.com/p/v8/issues/detail?id=2628
+ profiling_interval_ms = 500;
+#endif
+
+ // Cold run.
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+ cpu_profiler->StartCpuProfiling(profile_name);
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(profiling_interval_ms) };
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+ const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+ CHECK_NE(NULL, profile);
+
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+
+ CHECK_EQ(v8::String::New("cpu_profiler_sourceURL_source.js"),
+ startNode->GetScriptResourceName());
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
+
+TEST(LogExistingFunctionSourceURLCheck) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::New(cpu_profiler_sourceURL_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("start")));
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ int32_t profiling_interval_ms = 200;
+
+ // Warm up.
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(profiling_interval_ms) };
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+
+#if defined(_WIN32) || defined(_WIN64)
+ // 200ms is not enough on Windows. See
+ // https://code.google.com/p/v8/issues/detail?id=2628
+ profiling_interval_ms = 500;
+#endif
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+ cpu_profiler->StartCpuProfiling(profile_name);
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+ const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+ CHECK_NE(NULL, profile);
+
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ CHECK_EQ(v8::String::New("cpu_profiler_sourceURL_source.js"),
+ startNode->GetScriptResourceName());
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 68ed83d..72d124f 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2498,15 +2498,15 @@
f->shared()->code()->type_feedback_info())->type_feedback_cells());
CHECK_EQ(2, cells->CellCount());
- CHECK(cells->Cell(0)->value()->IsJSFunction());
- CHECK(cells->Cell(1)->value()->IsJSFunction());
+ CHECK(cells->GetCell(0)->value()->IsJSFunction());
+ CHECK(cells->GetCell(1)->value()->IsJSFunction());
SimulateIncrementalMarking();
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
CHECK_EQ(2, cells->CellCount());
- CHECK(cells->Cell(0)->value()->IsTheHole());
- CHECK(cells->Cell(1)->value()->IsTheHole());
+ CHECK(cells->GetCell(0)->value()->IsTheHole());
+ CHECK(cells->GetCell(1)->value()->IsTheHole());
}
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 45cb39c..f6f2172 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -557,7 +557,7 @@
}
} else { // 32-bit.
if (v8::internal::Snapshot::IsEnabled()) {
- CHECK_LE(delta, 2900 * 1024);
+ CHECK_LE(delta, 2910 * 1024);
} else {
CHECK_LE(delta, 3400 * 1024);
}
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 8973d54..20c00c1 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -195,7 +195,8 @@
int data_space_used,
int code_space_used,
int map_space_used,
- int cell_space_used);
+ int cell_space_used,
+ int property_cell_space_used);
private:
FILE* fp_;
@@ -209,7 +210,8 @@
int data_space_used,
int code_space_used,
int map_space_used,
- int cell_space_used) {
+ int cell_space_used,
+ int property_cell_space_used) {
int file_name_length = StrLength(file_name_) + 10;
Vector<char> name = Vector<char>::New(file_name_length + 1);
OS::SNPrintF(name, "%s.size", file_name_);
@@ -221,6 +223,7 @@
fprintf(fp, "code %d\n", code_space_used);
fprintf(fp, "map %d\n", map_space_used);
fprintf(fp, "cell %d\n", cell_space_used);
+ fprintf(fp, "property cell %d\n", property_cell_space_used);
fclose(fp);
}
@@ -236,7 +239,8 @@
ser.CurrentAllocationAddress(OLD_DATA_SPACE),
ser.CurrentAllocationAddress(CODE_SPACE),
ser.CurrentAllocationAddress(MAP_SPACE),
- ser.CurrentAllocationAddress(CELL_SPACE));
+ ser.CurrentAllocationAddress(CELL_SPACE),
+ ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
return true;
}
@@ -425,7 +429,8 @@
p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
p_ser.CurrentAllocationAddress(CODE_SPACE),
p_ser.CurrentAllocationAddress(MAP_SPACE),
- p_ser.CurrentAllocationAddress(CELL_SPACE));
+ p_ser.CurrentAllocationAddress(CELL_SPACE),
+ p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
startup_sink.WriteSpaceUsed(
startup_serializer.CurrentAllocationAddress(NEW_SPACE),
@@ -433,7 +438,8 @@
startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
startup_serializer.CurrentAllocationAddress(CODE_SPACE),
startup_serializer.CurrentAllocationAddress(MAP_SPACE),
- startup_serializer.CurrentAllocationAddress(CELL_SPACE));
+ startup_serializer.CurrentAllocationAddress(CELL_SPACE),
+ startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
startup_name.Dispose();
}
}
@@ -446,7 +452,8 @@
OS::SNPrintF(name, "%s.size", file_name);
FILE* fp = OS::FOpen(name.start(), "r");
name.Dispose();
- int new_size, pointer_size, data_size, code_size, map_size, cell_size;
+ int new_size, pointer_size, data_size, code_size, map_size, cell_size,
+ property_cell_size;
#ifdef _MSC_VER
// Avoid warning about unsafe fscanf from MSVC.
// Please note that this is only fine if %c and %s are not being used.
@@ -458,6 +465,7 @@
CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
+ CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
#ifdef _MSC_VER
#undef fscanf
#endif
@@ -468,6 +476,7 @@
deserializer->set_reservation(CODE_SPACE, code_size);
deserializer->set_reservation(MAP_SPACE, map_size);
deserializer->set_reservation(CELL_SPACE, cell_size);
+ deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
}
@@ -566,7 +575,8 @@
p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
p_ser.CurrentAllocationAddress(CODE_SPACE),
p_ser.CurrentAllocationAddress(MAP_SPACE),
- p_ser.CurrentAllocationAddress(CELL_SPACE));
+ p_ser.CurrentAllocationAddress(CELL_SPACE),
+ p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
startup_sink.WriteSpaceUsed(
startup_serializer.CurrentAllocationAddress(NEW_SPACE),
@@ -574,7 +584,8 @@
startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
startup_serializer.CurrentAllocationAddress(CODE_SPACE),
startup_serializer.CurrentAllocationAddress(MAP_SPACE),
- startup_serializer.CurrentAllocationAddress(CELL_SPACE));
+ startup_serializer.CurrentAllocationAddress(CELL_SPACE),
+ startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
startup_name.Dispose();
}
}
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index 3cdfdad..9729488 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -51,7 +51,8 @@
Null(Type::Null(), isolate),
Undefined(Type::Undefined(), isolate),
Number(Type::Number(), isolate),
- Smi(Type::Smi(), isolate),
+ Integer31(Type::Integer31(), isolate),
+ Integer32(Type::Integer32(), isolate),
Double(Type::Double(), isolate),
Name(Type::Name(), isolate),
UniqueName(Type::UniqueName(), isolate),
@@ -72,7 +73,7 @@
array = isolate->factory()->NewJSArray(20);
ObjectClass = handle(Type::Class(object_map), isolate);
ArrayClass = handle(Type::Class(array_map), isolate);
- SmiConstant = handle(Type::Constant(smi, isolate), isolate);
+ Integer31Constant = handle(Type::Constant(smi, isolate), isolate);
ObjectConstant1 = handle(Type::Constant(object1), isolate);
ObjectConstant2 = handle(Type::Constant(object2), isolate);
ArrayConstant = handle(Type::Constant(array), isolate);
@@ -85,7 +86,8 @@
Handle<Type> Null;
Handle<Type> Undefined;
Handle<Type> Number;
- Handle<Type> Smi;
+ Handle<Type> Integer31;
+ Handle<Type> Integer32;
Handle<Type> Double;
Handle<Type> Name;
Handle<Type> UniqueName;
@@ -101,7 +103,7 @@
Handle<Type> ObjectClass;
Handle<Type> ArrayClass;
- Handle<Type> SmiConstant;
+ Handle<Type> Integer31Constant;
Handle<Type> ObjectConstant1;
Handle<Type> ObjectConstant2;
Handle<Type> ArrayConstant;
@@ -168,12 +170,12 @@
HandleScope scope(isolate);
HandlifiedTypes T(isolate);
- CHECK(IsConstant(*T.SmiConstant));
+ CHECK(IsConstant(*T.Integer31Constant));
CHECK(IsConstant(*T.ObjectConstant1));
CHECK(IsConstant(*T.ObjectConstant2));
CHECK(IsConstant(*T.ArrayConstant));
- CHECK(*T.smi == AsConstant(*T.SmiConstant));
+ CHECK(*T.smi == AsConstant(*T.Integer31Constant));
CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
@@ -224,9 +226,12 @@
CheckUnordered(T.Boolean, T.Undefined);
CheckSub(T.Number, T.Any);
- CheckSub(T.Smi, T.Number);
+ CheckSub(T.Integer31, T.Number);
+ CheckSub(T.Integer32, T.Number);
CheckSub(T.Double, T.Number);
- CheckUnordered(T.Smi, T.Double);
+ CheckSub(T.Integer31, T.Integer32);
+ CheckUnordered(T.Integer31, T.Double);
+ CheckUnordered(T.Integer32, T.Double);
CheckSub(T.Name, T.Any);
CheckSub(T.UniqueName, T.Any);
@@ -255,8 +260,9 @@
CheckSub(T.ArrayClass, T.Object);
CheckUnordered(T.ObjectClass, T.ArrayClass);
- CheckSub(T.SmiConstant, T.Smi);
- CheckSub(T.SmiConstant, T.Number);
+ CheckSub(T.Integer31Constant, T.Integer31);
+ CheckSub(T.Integer31Constant, T.Integer32);
+ CheckSub(T.Integer31Constant, T.Number);
CheckSub(T.ObjectConstant1, T.Object);
CheckSub(T.ObjectConstant2, T.Object);
CheckSub(T.ArrayConstant, T.Object);
@@ -308,9 +314,9 @@
CheckDisjoint(T.Boolean, T.Undefined);
CheckOverlap(T.Number, T.Any);
- CheckOverlap(T.Smi, T.Number);
+ CheckOverlap(T.Integer31, T.Number);
CheckOverlap(T.Double, T.Number);
- CheckDisjoint(T.Smi, T.Double);
+ CheckDisjoint(T.Integer32, T.Double);
CheckOverlap(T.Name, T.Any);
CheckOverlap(T.UniqueName, T.Any);
@@ -340,9 +346,10 @@
CheckOverlap(T.ArrayClass, T.ArrayClass);
CheckDisjoint(T.ObjectClass, T.ArrayClass);
- CheckOverlap(T.SmiConstant, T.Smi);
- CheckOverlap(T.SmiConstant, T.Number);
- CheckDisjoint(T.SmiConstant, T.Double);
+ CheckOverlap(T.Integer31Constant, T.Integer31);
+ CheckOverlap(T.Integer31Constant, T.Integer32);
+ CheckOverlap(T.Integer31Constant, T.Number);
+ CheckDisjoint(T.Integer31Constant, T.Double);
CheckOverlap(T.ObjectConstant1, T.Object);
CheckOverlap(T.ObjectConstant2, T.Object);
CheckOverlap(T.ArrayConstant, T.Object);
@@ -425,21 +432,22 @@
CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
CheckSub(T.Union(T.ObjectClass, T.Number), T.Any);
- CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number));
+ CheckSub(T.Union(T.ObjectClass, T.Integer31), T.Union(T.Object, T.Number));
CheckSub(T.Union(T.ObjectClass, T.Array), T.Object);
CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array);
CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object);
CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
// Bitset-constant
- CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number)));
+ CHECK(IsBitset(Type::Union(T.Integer31Constant, T.Number)));
CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number)));
- CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
+ CheckEqual(T.Union(T.Integer31Constant, T.Number), T.Number);
CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
- CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number));
+ CheckSub(
+ T.Union(T.ObjectConstant1, T.Integer32), T.Union(T.Object, T.Number));
CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object);
CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array);
CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object);
@@ -516,8 +524,8 @@
T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
// Union-union
- CHECK(IsBitset(
- Type::Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array))));
+ CHECK(IsBitset(Type::Union(
+ T.Union(T.Number, T.ArrayClass), T.Union(T.Integer32, T.Array))));
CheckEqual(
T.Union(T.Union(T.ObjectConstant2, T.ObjectConstant1),
@@ -528,6 +536,6 @@
T.Union(T.ObjectConstant1, T.ArrayConstant)),
T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant));
CheckEqual(
- T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)),
+ T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Integer31, T.Array)),
T.Union(T.Number, T.Array));
}
diff --git a/test/cctest/test-weaktypedarrays.cc b/test/cctest/test-weaktypedarrays.cc
index aef610d..ead5734 100644
--- a/test/cctest/test-weaktypedarrays.cc
+++ b/test/cctest/test-weaktypedarrays.cc
@@ -44,7 +44,7 @@
static int CountArrayBuffersInWeakList(Heap* heap) {
int count = 0;
for (Object* o = heap->array_buffers_list();
- o != Smi::FromInt(0);
+ !o->IsUndefined();
o = JSArrayBuffer::cast(o)->weak_next()) {
count++;
}
@@ -54,7 +54,7 @@
static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
for (Object* o = heap->array_buffers_list();
- o != Smi::FromInt(0);
+ !o->IsUndefined();
o = JSArrayBuffer::cast(o)->weak_next()) {
if (ab == o) return true;
}
@@ -65,7 +65,7 @@
static int CountTypedArrays(JSArrayBuffer* array_buffer) {
int count = 0;
for (Object* o = array_buffer->weak_first_array();
- o != Smi::FromInt(0);
+ !o->IsUndefined();
o = JSTypedArray::cast(o)->weak_next()) {
count++;
}
@@ -76,7 +76,7 @@
static bool HasTypedArrayInWeakList(JSArrayBuffer* array_buffer,
JSTypedArray* ta) {
for (Object* o = array_buffer->weak_first_array();
- o != Smi::FromInt(0);
+ !o->IsUndefined();
o = JSTypedArray::cast(o)->weak_next()) {
if (ta == o) return true;
}
diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js
index df1bd22..75d01b5 100644
--- a/test/mjsunit/compiler/inline-arguments.js
+++ b/test/mjsunit/compiler/inline-arguments.js
@@ -266,3 +266,46 @@
}
}
})();
+
+
+// Test materialization of arguments object with values in registers.
+(function () {
+ "use strict";
+ var forceDeopt = { deopt:false };
+ function inner(a,b,c,d,e,f,g,h,i,j) {
+ var args = arguments;
+ forceDeopt.deopt;
+ assertSame(10, args.length);
+ assertSame(a, args[0]);
+ assertSame(b, args[1]);
+ assertSame(c, args[2]);
+ assertSame(d, args[3]);
+ assertSame(e, args[4]);
+ assertSame(f, args[5]);
+ assertSame(g, args[6]);
+ assertSame(h, args[7]);
+ assertSame(i, args[8]);
+ assertSame(j, args[9]);
+ }
+
+ var a = 0.5;
+ var b = 1.7;
+ var c = 123;
+ function outer() {
+ inner(
+ a - 0.3, // double in double register
+ b + 2.3, // integer in double register
+ c + 321, // integer in general register
+ c - 456, // integer in stack slot
+ a + 0.1, a + 0.2, a + 0.3, a + 0.4, a + 0.5,
+ a + 0.6 // double in stack slot
+ );
+ }
+
+ outer();
+ outer();
+ %OptimizeFunctionOnNextCall(outer);
+ outer();
+ delete forceDeopt.deopt;
+ outer();
+})();
diff --git a/test/mjsunit/compiler/parallel-proto-change.js b/test/mjsunit/compiler/parallel-proto-change.js
index 74e6d86..aa1ac6d 100644
--- a/test/mjsunit/compiler/parallel-proto-change.js
+++ b/test/mjsunit/compiler/parallel-proto-change.js
@@ -25,7 +25,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --parallel-recompilation
+// Flags: --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+ assertTrue(%GetOptimizationStatus(fun) != 1);
+}
function f(foo) { return foo.bar(); }
@@ -36,10 +41,10 @@
assertEquals(1, f(o));
%OptimizeFunctionOnNextCall(f, "parallel");
-assertEquals(1, f(o));
-// Change the prototype chain during optimization.
+assertEquals(1, f(o)); // Trigger optimization.
+assertUnoptimized(f); // Optimization not yet done.
+// Change the prototype chain during optimization to trigger map invalidation.
o.__proto__.__proto__ = { bar: function() { return 2; } };
-
-%WaitUntilOptimized(f);
-
+%CompleteOptimization(f); // Conclude optimization with...
+assertUnoptimized(f); // ... bailing out due to map dependency.
assertEquals(2, f(o));
diff --git a/test/mjsunit/harmony/generators-iteration.js b/test/mjsunit/harmony/generators-iteration.js
index 01facd0..2ca35f2 100644
--- a/test/mjsunit/harmony/generators-iteration.js
+++ b/test/mjsunit/harmony/generators-iteration.js
@@ -324,6 +324,28 @@
"foo",
[2, "1foo3", 5, "4foo6", "foofoo"]);
+// Generator function instances.
+TestGenerator(GeneratorFunction(),
+ [undefined],
+ "foo",
+ [undefined]);
+
+TestGenerator(new GeneratorFunction(),
+ [undefined],
+ "foo",
+ [undefined]);
+
+TestGenerator(GeneratorFunction('yield 1;'),
+ [1, undefined],
+ "foo",
+ [1, undefined]);
+
+TestGenerator(
+ function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) },
+ [3, undefined],
+ "foo",
+ [3, undefined]);
+
function TestTryCatch(instantiate) {
function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
function Sentinel() {}
diff --git a/test/mjsunit/harmony/generators-runtime.js b/test/mjsunit/harmony/generators-runtime.js
index 7667deb..aef063b 100644
--- a/test/mjsunit/harmony/generators-runtime.js
+++ b/test/mjsunit/harmony/generators-runtime.js
@@ -110,6 +110,9 @@
// Not all functions are generators.
assertTrue(f instanceof Function); // Sanity check.
assertTrue(!(f instanceof GeneratorFunction));
+
+ assertTrue((new GeneratorFunction()) instanceof GeneratorFunction);
+ assertTrue(GeneratorFunction() instanceof GeneratorFunction);
}
TestGeneratorFunction();
diff --git a/test/mjsunit/harmony/iteration-syntax.js b/test/mjsunit/harmony/iteration-syntax.js
index 21149c0..3bda78e 100644
--- a/test/mjsunit/harmony/iteration-syntax.js
+++ b/test/mjsunit/harmony/iteration-syntax.js
@@ -54,6 +54,11 @@
assertThrows("function f() { for (let of y) { } }", SyntaxError);
assertThrows("function f() { for (let of of) { } }", SyntaxError);
+assertThrows("function f() { for (x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (var x = 3 of y) { } }", SyntaxError);
+assertThrows("function f() { for (let x = 3 of y) { } }", SyntaxError);
+
+
// Alack, this appears to be valid.
function f() { for (of of y) { } }
function f() { for (let of of y) { } }
diff --git a/test/mjsunit/manual-parallel-recompile.js b/test/mjsunit/manual-parallel-recompile.js
index 8d660e0..f090ff4 100644
--- a/test/mjsunit/manual-parallel-recompile.js
+++ b/test/mjsunit/manual-parallel-recompile.js
@@ -25,12 +25,17 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --allow-natives-syntax --expose-gc --parallel-recompilation
+// Flags: --allow-natives-syntax --expose-gc
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
function assertUnoptimized(fun) {
assertTrue(%GetOptimizationStatus(fun) != 1);
}
+function assertOptimized(fun) {
+ assertTrue(%GetOptimizationStatus(fun) != 2);
+}
+
function f(x) {
var xx = x * x;
var xxstr = xx.toString();
@@ -53,10 +58,13 @@
%OptimizeFunctionOnNextCall(f, "parallel");
%OptimizeFunctionOnNextCall(g, "parallel");
-f(g(2));
+f(g(2)); // Trigger optimization.
-assertUnoptimized(f);
+assertUnoptimized(f); // Not yet optimized.
assertUnoptimized(g);
-%WaitUntilOptimized(f);
-%WaitUntilOptimized(g);
+%CompleteOptimization(f); // Wait till optimized code is installed.
+%CompleteOptimization(g);
+
+assertOptimized(f); // Optimized now.
+assertOptimized(g);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 8d6274b..585d503 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -47,10 +47,6 @@
stack-traces-gc: PASS || FAIL
##############################################################################
-# TODO(wingo): Re-enable when GC bug from r15060 is solved.
-harmony/generators-iteration: SKIP
-
-##############################################################################
# Too slow in debug mode with --stress-opt mode.
compiler/regress-stacktrace-methods: PASS, SKIP if $mode == debug
compiler/regress-funcaller: PASS, SKIP if $mode == debug
diff --git a/test/mjsunit/parallel-initial-prototype-change.js b/test/mjsunit/parallel-initial-prototype-change.js
new file mode 100644
index 0000000..5544beb
--- /dev/null
+++ b/test/mjsunit/parallel-initial-prototype-change.js
@@ -0,0 +1,50 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+ assertTrue(%GetOptimizationStatus(fun) != 1);
+}
+
+function f1(a, i) {
+ return a[i] + 0.5;
+}
+
+var arr = [0.0,,2.5];
+assertEquals(0.5, f1(arr, 0));
+assertEquals(0.5, f1(arr, 0));
+
+// Optimized code of f1 depends on initial object and array maps.
+%OptimizeFunctionOnNextCall(f1, "parallel");
+assertEquals(0.5, f1(arr, 0));
+assertUnoptimized(f1); // Not yet optimized.
+Object.prototype[1] = 1.5; // Invalidate current initial object map.
+assertEquals(2, f1(arr, 1));
+%CompleteOptimization(f1); // Conclude optimization with...
+assertUnoptimized(f1); // ... bailing out due to map dependency.
diff --git a/test/mjsunit/parallel-invalidate-transition-map.js b/test/mjsunit/parallel-invalidate-transition-map.js
new file mode 100644
index 0000000..42a266f
--- /dev/null
+++ b/test/mjsunit/parallel-invalidate-transition-map.js
@@ -0,0 +1,56 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --track-fields --track-double-fields --allow-natives-syntax
+// Flags: --parallel-recompilation --parallel-recompilation-delay=50
+
+function assertUnoptimized(fun) {
+ assertTrue(%GetOptimizationStatus(fun) != 1);
+}
+
+function new_object() {
+ var o = {};
+ o.a = 1;
+ o.b = 2;
+ return o;
+}
+
+function add_field(obj) {
+ obj.c = 3;
+}
+
+add_field(new_object());
+add_field(new_object());
+%OptimizeFunctionOnNextCall(add_field, "parallel");
+
+var o = new_object();
+add_field(o); // Trigger optimization.
+assertUnoptimized(add_field); // Not yet optimized.
+o.c = 2.2; // Invalidate transition map.
+%CompleteOptimization(add_field); // Conclude optimization with...
+assertUnoptimized(add_field); // ... bailing out due to map dependency.
+
diff --git a/test/mjsunit/parallel-optimize-disabled.js b/test/mjsunit/parallel-optimize-disabled.js
index 86b375c..479684d 100644
--- a/test/mjsunit/parallel-optimize-disabled.js
+++ b/test/mjsunit/parallel-optimize-disabled.js
@@ -43,4 +43,4 @@
%OptimizeFunctionOnNextCall(g, "parallel");
f(0); // g() is disabled for optimization on inlining attempt.
// Attempt to optimize g() should not run into any assertion.
-%WaitUntilOptimized(g);
+%CompleteOptimization(g);
diff --git a/test/mjsunit/regress/regress-crbug-245480.js b/test/mjsunit/regress/regress-crbug-245480.js
new file mode 100644
index 0000000..4769486
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-245480.js
@@ -0,0 +1,90 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
+// Flags: --track-allocation-sites --noalways-opt
+
+// Test element kind of objects.
+// Since --smi-only-arrays affects builtins, its default setting at compile
+// time sticks if built with snapshot. If --smi-only-arrays is deactivated
+// by default, only a no-snapshot build actually has smi-only arrays enabled
+// in this test case. Depending on whether smi-only arrays are actually
+// enabled, this test takes the appropriate code path to check smi-only arrays.
+
+// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
+support_smi_only_arrays = true;
+
+if (support_smi_only_arrays) {
+ print("Tests include smi-only arrays.");
+} else {
+ print("Tests do NOT include smi-only arrays.");
+}
+
+function isHoley(obj) {
+ if (%HasFastHoleyElements(obj)) return true;
+ return false;
+}
+
+function assertHoley(obj, name_opt) {
+ assertEquals(true, isHoley(obj), name_opt);
+}
+
+function assertNotHoley(obj, name_opt) {
+ assertEquals(false, isHoley(obj), name_opt);
+}
+
+if (support_smi_only_arrays) {
+ function create_array(arg) {
+ return new Array(arg);
+ }
+
+ obj = create_array(0);
+ assertNotHoley(obj);
+ create_array(0);
+ %OptimizeFunctionOnNextCall(create_array);
+ obj = create_array(10);
+ assertHoley(obj);
+}
+
+// The code below would assert in debug or crash in release
+function f(length) {
+ return new Array(length)
+}
+
+f(0);
+f(0);
+%OptimizeFunctionOnNextCall(f);
+var a = f(10);
+
+function g(a) {
+ return a[0];
+}
+
+var b = [0];
+g(b);
+g(b);
+assertEquals(undefined, g(a));
\ No newline at end of file
diff --git a/tools/v8-info.sh b/tools/v8-info.sh
new file mode 100755
index 0000000..1f25d14
--- /dev/null
+++ b/tools/v8-info.sh
@@ -0,0 +1,161 @@
+#!/bin/bash
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+########## Global variable definitions
+
+BASE_URL="https://code.google.com/p/v8/source/list"
+VERSION="src/version.cc"
+MAJOR="MAJOR_VERSION"
+MINOR="MINOR_VERSION"
+BUILD="BUILD_NUMBER"
+PATCH="PATCH_LEVEL"
+
+V8="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+########## Function definitions
+
+cd $V8
+
+usage() {
+cat << EOF
+usage: $0 OPTIONS
+
+Fetches V8 revision information from a git-svn checkout.
+
+OPTIONS:
+ -h Show this message.
+
+ -i Print revision info for all branches matching the V8 version.
+ Example usage: $0 -i 3.19.10$
+ Output format: [Git hash] [SVN revision] [V8 version]
+
+ -v Print the V8 version tag for a trunk SVN revision.
+ Example usage: $0 -v 14981
+ Output format: [V8 version]
+
+ -m Print all patches that were merged to the specified V8 branch.
+ Example usage: $0 -m 3.18
+ Output format: [V8 version] [SVN revision] [SVN patch merged]*.
+
+ -p Print all patches merged to a specific V8 point-release.
+ Example usage: $0 -p 3.19.12.1
+ Output format: [SVN patch merged]*
+
+ -u Print a link to all SVN revisions between two V8 revision tags.
+ Example usage: $0 -u 3.19.10:3.19.11
+EOF
+}
+
+tags() {
+ git for-each-ref --format="%(objectname) %(refname:short)" refs/remotes/svn
+}
+
+tag_revision() {
+ cut -d" " -f1
+}
+
+tag_log() {
+ git log --format="%h %ci %ce %s" -1 $1
+}
+
+v8_hash() {
+ tags | grep "svn/tags/$1$" | tag_revision
+}
+
+point_merges() {
+ echo $1 | grep -o "r[0-9]\+"
+}
+
+hash_to_svn() {
+ git svn log -1 --oneline $1 | cut -d" " -f1
+}
+
+tag_version() {
+ tags | grep svn/tags/$1 | while read tag; do
+ id=$(echo $tag | grep -o "[^/]*$")
+ rev=$(echo $tag | tag_revision)
+ svn=$(hash_to_svn $rev)
+ echo $rev $svn $id
+ done
+}
+
+svn_rev() {
+ git svn find-rev $2 svn/$1
+}
+
+v8_rev() {
+ cd $(git rev-parse --show-toplevel)
+ rev=$(git show $1:$VERSION \
+ | grep "#define" \
+ | grep "$MAJOR\|$MINOR\|$BUILD\|$PATCH" \
+ | grep -o "[0-9]\+$" \
+ | tr "\\n" ".")
+ echo ${rev%?}
+}
+
+merges_to_branch() {
+ git cherry -v svn/trunk svn/$1 | while read merge; do
+ h=$(echo $merge | cut -d" " -f2)
+ svn=$(svn_rev $1 $h)
+ merges=$(echo $merge | grep -o "r[0-9]\+")
+ rev=$(v8_rev $h)
+ echo $rev r$svn $merges
+ done
+}
+
+url_for() {
+ first=$(svn_rev trunk $(v8_hash $(echo $1 | cut -d":" -f1)))
+ last=$(svn_rev trunk $(v8_hash $(echo $1 | cut -d":" -f2)))
+ num=$[ $last - $first]
+ echo "$BASE_URL?num=$num&start=$last"
+}
+
+########## Option parsing
+
+while getopts ":hi:v:m:p:u:" OPTION ; do
+ case $OPTION in
+ h) usage
+ exit 0
+ ;;
+ i) tag_version $OPTARG
+ ;;
+ v) v8_rev $(svn_rev trunk r$OPTARG)
+ ;;
+ m) merges_to_branch $OPTARG
+ ;;
+ p) echo $(point_merges "$(tag_log $(v8_hash $OPTARG)^1)")
+ ;;
+ u) url_for $OPTARG
+ ;;
+ ?) echo "Illegal option: -$OPTARG"
+ usage
+ exit 1
+ ;;
+ esac
+done
diff --git a/tools/v8-rolls.sh b/tools/v8-rolls.sh
new file mode 100755
index 0000000..590e05c
--- /dev/null
+++ b/tools/v8-rolls.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+########## Global variable definitions
+
+DEPS_STRING='"v8_revision":'
+INFO=tools/v8-info.sh
+
+V8="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+
+########## Function definitions
+
+usage() {
+cat << EOF
+usage: $0 OPTIONS
+
+Run in chromium/src to get information about V8 rolls.
+
+OPTIONS:
+ -h Show this message.
+ -n Number of rolls to print information about.
+ -s Chromium git hash to start printing V8 information about.
+EOF
+}
+
+v8_line() {
+ git show $1:DEPS | grep -n $DEPS_STRING | cut -d":" -f1
+}
+
+v8_info() {
+ git blame -L$(v8_line $1),+1 $1 DEPS | grep $DEPS_STRING
+}
+
+v8_svn() {
+ sed -e 's/^.*"\([0-9]\+\)",$/\1/'
+}
+
+v8_roll() {
+ cut -d" " -f1
+}
+
+find_rev() {
+ git svn find-rev $1
+}
+
+msg() {
+ msg=$(git log --format="%h %ci %ce" -1 $1)
+ h=$(echo $msg | cut -d" " -f1)
+ d=$(echo $msg | cut -d" " -f2)
+ t=$(echo $msg | cut -d" " -f3)
+ a=$(echo $msg | cut -d" " -f5)
+ a1=$(echo $a | cut -d"@" -f1)
+ a2=$(echo $a | cut -d"@" -f2)
+ echo $h $d $t $a1@$a2
+}
+
+v8_revision() {
+ cd $V8
+ $INFO -v $1
+}
+
+rolls() {
+ roll=$2
+ for i in $(seq 1 $1); do
+ info=$(v8_info $roll)
+ roll=$(echo $info | v8_roll $roll)
+ trunk=$(echo $info | v8_svn $roll)
+ echo "$(v8_revision $trunk) $trunk $(find_rev $roll) $(msg $roll)"
+ roll=$roll^1
+ done
+}
+
+########## Option parsing
+
+REVISIONS=1
+START=HEAD
+
+while getopts ":hn:s:" OPTION ; do
+ case $OPTION in
+ h) usage
+ exit 0
+ ;;
+ n) REVISIONS=$OPTARG
+ ;;
+ s) START=$OPTARG
+ ;;
+ ?) echo "Illegal option: -$OPTARG"
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+rolls $REVISIONS $START