Version 3.17.11
Added a version of the v8::HandleScope constructor with an v8::Isolate parameter and made AdjustAmountOfExternalAllocatedMemory an instance method of v8::Isolate. (issue 2487)
Fixed two register allocator bugs (off-by-one error/failure propagation). (issue 2576)
Fixed huge heap snapshot when a heavily shared context has many variables. (Chromium issue 145687)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@13956 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 4ec3936..47928a6 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -666,11 +666,21 @@
HandleScope::HandleScope() {
- i::Isolate* isolate = i::Isolate::Current();
- API_ENTRY_CHECK(isolate, "HandleScope::HandleScope");
+ Initialize(reinterpret_cast<Isolate*>(i::Isolate::Current()));
+}
+
+
+HandleScope::HandleScope(Isolate* isolate) {
+ Initialize(isolate);
+}
+
+
+void HandleScope::Initialize(Isolate* isolate) {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ API_ENTRY_CHECK(internal_isolate, "HandleScope::HandleScope");
v8::ImplementationUtilities::HandleScopeData* current =
- isolate->handle_scope_data();
- isolate_ = isolate;
+ internal_isolate->handle_scope_data();
+ isolate_ = internal_isolate;
prev_next_ = current->next;
prev_limit_ = current->limit;
is_closed_ = false;
@@ -686,7 +696,6 @@
void HandleScope::Leave() {
- ASSERT(isolate_ == i::Isolate::Current());
v8::ImplementationUtilities::HandleScopeData* current =
isolate_->handle_scope_data();
current->level--;
@@ -1884,7 +1893,7 @@
v8::TryCatch::~TryCatch() {
ASSERT(isolate_ == i::Isolate::Current());
if (rethrow_) {
- v8::HandleScope scope;
+ v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate_));
v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
isolate_->UnregisterTryCatchHandler(this);
v8::ThrowException(exc);
@@ -1976,7 +1985,7 @@
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
Local<String> result = Utils::ToLocal(raw_result);
@@ -1990,7 +1999,7 @@
return Local<String>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSMessageObject> message =
i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
// Return this.script.name.
@@ -2009,7 +2018,7 @@
return Local<Value>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSMessageObject> message =
i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
// Return this.script.data.
@@ -2027,7 +2036,7 @@
return Local<v8::StackTrace>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSMessageObject> message =
i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
@@ -2147,7 +2156,7 @@
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
Utils::OpenHandle(this),
@@ -2177,7 +2186,7 @@
return Local<StackFrame>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSArray> self = Utils::OpenHandle(this);
i::Object* raw_object = self->GetElementNoExceptionThrown(index);
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
@@ -2254,7 +2263,7 @@
return Local<String>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> name = GetProperty(self, "scriptName");
if (!name->IsString()) {
@@ -2270,7 +2279,7 @@
return Local<String>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
if (!name->IsString()) {
@@ -2286,7 +2295,7 @@
return Local<String>();
}
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> name = GetProperty(self, "functionName");
if (!name->IsString()) {
@@ -3280,7 +3289,7 @@
ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
return false);
ENTER_V8(isolate);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
return i::JSObject::DeleteElement(self, index)->IsTrue();
}
@@ -3858,7 +3867,7 @@
ENTER_V8(isolate);
i::Logger::TimerEventScope timer_scope(
isolate, i::Logger::TimerEventScope::v8_execute);
- HandleScope scope;
+ HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
@@ -4011,31 +4020,30 @@
class Visitor {
public:
- explicit Visitor()
+ inline explicit Visitor()
: utf8_length_(0),
state_(kInitialState) {}
- template<typename Char>
- inline void Visit(const Char* chars, int length) {
+ void VisitOneByteString(const uint8_t* chars, int length) {
+ int utf8_length = 0;
+ // Add in length 1 for each non-ASCII character.
+ for (int i = 0; i < length; i++) {
+ utf8_length += *chars++ >> 7;
+ }
+ // Add in length 1 for each character.
+ utf8_length_ = utf8_length + length;
+ state_ = kInitialState;
+ }
+
+ void VisitTwoByteString(const uint16_t* chars, int length) {
int utf8_length = 0;
int last_character = unibrow::Utf16::kNoPreviousCharacter;
for (int i = 0; i < length; i++) {
uint16_t c = chars[i];
utf8_length += unibrow::Utf8::Length(c, last_character);
- if (sizeof(Char) > 1) {
- last_character = c;
- }
+ last_character = c;
}
utf8_length_ = utf8_length;
- }
-
- void VisitOneByteString(const uint8_t* chars, int length) {
- Visit(chars, length);
- state_ = kInitialState;
- }
-
- void VisitTwoByteString(const uint16_t* chars, int length) {
- Visit(chars, length);
uint8_t state = 0;
if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
state |= kStartsWithTrailingSurrogate;
@@ -4132,32 +4140,30 @@
if (right_as_cons == NULL) {
total_length += leaf_length;
MergeLeafRight(&total_length, &state, right_leaf_state);
- // Terminal node.
- if (left_as_cons == NULL) {
+ if (left_as_cons != NULL) {
+ // 1 Leaf node. Descend in place.
+ current = left_as_cons;
+ continue;
+ } else {
+ // Terminal node.
MergeTerminal(&total_length, state, state_out);
return total_length;
}
- } else if (left_as_cons != NULL) {
- // Both strings are ConsStrings.
- // Recurse on smallest.
- if (left->length() < right->length()) {
- total_length += Calculate(left_as_cons, &left_leaf_state);
- MergeLeafLeft(&total_length, &state, left_leaf_state);
- current = right_as_cons;
- continue;
- } else {
- total_length += Calculate(right_as_cons, &right_leaf_state);
- MergeLeafRight(&total_length, &state, right_leaf_state);
- current = left_as_cons;
- continue;
- }
- }
- // 1 leaf node. Do in place descent.
- if (left_as_cons != NULL) {
- current = left_as_cons;
- } else {
- ASSERT(right_as_cons != NULL);
+ } else if (left_as_cons == NULL) {
+ // 1 Leaf node. Descend in place.
current = right_as_cons;
+ continue;
+ }
+ // Both strings are ConsStrings.
+ // Recurse on smallest.
+ if (left->length() < right->length()) {
+ total_length += Calculate(left_as_cons, &left_leaf_state);
+ MergeLeafLeft(&total_length, &state, left_leaf_state);
+ current = right_as_cons;
+ } else {
+ total_length += Calculate(right_as_cons, &right_leaf_state);
+ MergeLeafRight(&total_length, &state, right_leaf_state);
+ current = left_as_cons;
}
}
UNREACHABLE();
@@ -4267,7 +4273,7 @@
if (sizeof(Char) == 1) {
for (; i < fast_length; i++) {
buffer +=
- Utf8::Encode(buffer, *chars++, Utf16::kNoPreviousCharacter);
+ Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
}
} else {
@@ -5783,14 +5789,21 @@
}
+intptr_t Isolate::AdjustAmountOfExternalAllocatedMemory(
+ intptr_t change_in_bytes) {
+ i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
+ return heap->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
+}
+
+
intptr_t V8::AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes) {
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
if (isolate == NULL || !isolate->IsInitialized() ||
IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) {
return 0;
}
- return isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
- change_in_bytes);
+ Isolate* isolate_ext = reinterpret_cast<Isolate*>(isolate);
+ return isolate_ext->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
}
@@ -6314,7 +6327,7 @@
if (!isolate->IsInitialized()) return Local<Value>();
ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
ENTER_V8(isolate);
- v8::HandleScope scope;
+ v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Debug* isolate_debug = isolate->debug();
isolate_debug->Load();
i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object());
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 85a523d..123013b 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -107,13 +107,13 @@
Address RelocInfo::target_address() {
- ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
return Assembler::target_address_at(pc_);
}
Address RelocInfo::target_address_address() {
- ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
+ ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
|| rmode_ == EXTERNAL_REFERENCE);
return reinterpret_cast<Address>(Assembler::target_pointer_address_at(pc_));
@@ -126,7 +126,7 @@
void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
- ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
Assembler::set_target_address_at(pc_, target);
if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
Object* target_code = Code::GetCodeFromTargetAddress(target);
@@ -321,7 +321,7 @@
Isolate::Current()->debug()->has_break_points()) {
visitor->VisitDebugTarget(this);
#endif
- } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+ } else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(this);
}
}
@@ -348,7 +348,7 @@
IsPatchedDebugBreakSlotSequence()))) {
StaticVisitor::VisitDebugTarget(heap, this);
#endif
- } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+ } else if (RelocInfo::IsRuntimeEntry(mode)) {
StaticVisitor::VisitRuntimeEntry(this);
}
}
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 142787b..2946b35 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -124,12 +124,7 @@
if (initial_capacity > 0) {
size += FixedArray::SizeFor(initial_capacity);
}
- __ AllocateInNewSpace(size,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT);
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
@@ -653,12 +648,12 @@
// -----------------------------------
Label gc_required;
- __ AllocateInNewSpace(JSValue::kSize,
- r0, // Result.
- r3, // Scratch.
- r4, // Scratch.
- &gc_required,
- TAG_OBJECT);
+ __ Allocate(JSValue::kSize,
+ r0, // Result.
+ r3, // Scratch.
+ r4, // Scratch.
+ &gc_required,
+ TAG_OBJECT);
// Initialising the String Object.
Register map = r3;
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index f2f6408..b1ffaea 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -166,12 +166,7 @@
__ pop(r3);
// Attempt to allocate new JSFunction in new space.
- __ AllocateInNewSpace(JSFunction::kSize,
- r0,
- r1,
- r2,
- &gc,
- TAG_OBJECT);
+ __ Allocate(JSFunction::kSize, r0, r1, r2, &gc, TAG_OBJECT);
__ IncrementCounter(counters->fast_new_closure_total(), 1, r6, r7);
@@ -298,12 +293,7 @@
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
// Attempt to allocate the context in new space.
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- r0,
- r1,
- r2,
- &gc,
- TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
// Load the function from the stack.
__ ldr(r3, MemOperand(sp, 0));
@@ -348,8 +338,7 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- r0, r1, r2, &gc, TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length), r0, r1, r2, &gc, TAG_OBJECT);
// Load the function from the stack.
__ ldr(r3, MemOperand(sp, 0));
@@ -435,7 +424,7 @@
if (mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS) {
flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT | flags);
}
- __ AllocateInNewSpace(size, r0, r1, r2, fail, flags);
+ __ Allocate(size, r0, r1, r2, fail, flags);
if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
__ mov(r2, Operand(Handle<Map>(masm->isolate()->heap()->
@@ -4513,7 +4502,7 @@
StubCompiler::GenerateLoadArrayLength(masm, receiver, r3, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4542,7 +4531,7 @@
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4573,7 +4562,7 @@
support_wrapper_);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4643,7 +4632,7 @@
__ bind(&miss);
- StubCompiler::GenerateStoreMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index eb1f988..1df1649 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1547,7 +1547,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index e10068f..7272f54 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -290,6 +290,13 @@
}
+void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ base_object()->PrintTo(stream);
+ stream->Add(" + %d", offset());
+}
+
+
void LCallConstantFunction::PrintDataTo(StringStream* stream) {
stream->Add("#%d / ", arity());
}
@@ -668,8 +675,12 @@
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
- operand->set_virtual_register(allocator_->GetVirtualRegister());
- if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
+ int vreg = allocator_->GetVirtualRegister();
+ if (!allocator_->AllocationOk()) {
+ Abort("Out of virtual registers while trying to allocate temp register.");
+ return NULL;
+ }
+ operand->set_virtual_register(vreg);
return operand;
}
@@ -928,7 +939,7 @@
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
HValue* value = instr->value();
if (value->EmitAtUses()) {
- HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
+ HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
return new(zone()) LGoto(successor->block_id());
@@ -1017,6 +1028,15 @@
}
+LInstruction* LChunkBuilder::DoInnerAllocatedObject(
+ HInnerAllocatedObject* inner_object) {
+ LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
+ LInnerAllocatedObject* result =
+ new(zone()) LInnerAllocatedObject(base_object);
+ return DefineAsRegister(result);
+}
+
+
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
return instr->HasNoUses()
? NULL
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index ca8b493..f49e8ce 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -191,7 +191,8 @@
V(LoadFieldByIndex) \
V(DateField) \
V(WrapReceiver) \
- V(Drop)
+ V(Drop) \
+ V(InnerAllocatedObject)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
@@ -1655,6 +1656,22 @@
};
+class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LInnerAllocatedObject(LOperand* base_object) {
+ inputs_[0] = base_object;
+ }
+
+ LOperand* base_object() { return inputs_[0]; }
+ int offset() { return hydrogen()->offset(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object")
+ DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject)
+};
+
+
class LThisFunction: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 6e2fc17..e8f96e4 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4341,6 +4341,13 @@
}
+void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
+ Register result = ToRegister(instr->result());
+ Register base = ToRegister(instr->base_object());
+ __ add(result, base, Operand(instr->offset()));
+}
+
+
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register object = ToRegister(instr->object());
Register value = ToRegister(instr->value());
@@ -5581,12 +5588,8 @@
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
- __ AllocateInNewSpace(instance_size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- TAG_OBJECT);
+ __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
+ TAG_OBJECT);
__ bind(deferred->exit());
if (FLAG_debug_code) {
@@ -5661,12 +5664,10 @@
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ AllocateInNewSpace(size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- flags);
+ if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+ flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+ }
+ __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ AllocateInNewSpace(size,
@@ -5899,7 +5900,7 @@
// Allocate all objects that are part of the literal in one big
// allocation. This avoids multiple limit checks.
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
@@ -5981,7 +5982,7 @@
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 1542447..e0e77cf 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1564,12 +1564,12 @@
}
-void MacroAssembler::AllocateInNewSpace(int object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags) {
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1597,21 +1597,22 @@
// The values must be adjacent in memory to allow the use of LDM.
// Also, assert that the registers are numbered such that the values
// are loaded in the correct order.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
+
intptr_t top =
- reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+ reinterpret_cast<intptr_t>(allocation_top.address());
intptr_t limit =
- reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+ reinterpret_cast<intptr_t>(allocation_limit.address());
ASSERT((limit - top) == kPointerSize);
ASSERT(result.code() < ip.code());
// Set up allocation top address and object size registers.
Register topaddr = scratch1;
Register obj_size_reg = scratch2;
- mov(topaddr, Operand(new_space_allocation_top));
+ mov(topaddr, Operand(allocation_top));
Operand obj_size_operand = Operand(object_size);
if (!obj_size_operand.is_single_instruction(this)) {
// We are about to steal IP, so we need to load this value first
@@ -1639,6 +1640,7 @@
if ((flags & DOUBLE_ALIGNMENT) != 0) {
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC);
Label aligned;
@@ -1675,6 +1677,7 @@
Register scratch2,
Label* gc_required,
AllocationFlags flags) {
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1858,12 +1861,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -1878,12 +1877,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -1898,12 +1893,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -1918,12 +1909,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -2238,7 +2225,8 @@
void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
- ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+ ASSERT(allow_stub_calls_ ||
+ stub->CompilingCallsToThisStubIsGCSafe(isolate()));
Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, cond);
}
@@ -2348,7 +2336,7 @@
bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
- return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
+ return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(isolate());
}
@@ -2544,7 +2532,15 @@
!scratch.is(input_low));
ASSERT(!double_input.is(double_scratch));
- Label overflow, out_of_range, negate, done;
+ Label out_of_range, negate, done;
+
+ vcvt_s32_f64(double_scratch.low(), double_input);
+ vmov(result, double_scratch.low());
+
+ // If result is not saturated (0x7fffffff or 0x80000000), we are done.
+ sub(scratch, result, Operand(1));
+ cmp(scratch, Operand(0x7ffffffe));
+ b(lt, &done);
vmov(input_low, input_high, double_input);
Ubfx(scratch, input_high,
@@ -2552,20 +2548,9 @@
// Load scratch with exponent - 1. This is faster than loading
// with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
- // Compare exponent with 31 (compare exponent - 1 with 30).
- cmp(scratch, Operand(30));
- b(ge, &overflow);
- // Exponent is less than 31 so vcvt will never saturate.
- // So, just return the result.
- vcvt_s32_f64(double_scratch.low(), double_input);
- vmov(result, double_scratch.low());
- b(&done);
-
- bind(&overflow);
// If exponent is greater than or equal to 84, the 32 less significant
// bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
// the result is 0.
- // This test also catch Nan and infinities which also return 0.
// Compare exponent with 84 (compare exponent - 1 with 83).
cmp(scratch, Operand(83));
b(ge, &out_of_range);
@@ -3231,13 +3216,8 @@
TaggingMode tagging_mode) {
// Allocate an object in the heap for the heap number and tag it as a heap
// object.
- AllocateInNewSpace(HeapNumber::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- tagging_mode == TAG_RESULT ? TAG_OBJECT :
- NO_ALLOCATION_FLAGS);
+ Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
+ tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
// Store heap number map in the allocated object.
AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 05ede68..5cbe995 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -665,19 +665,20 @@
// ---------------------------------------------------------------------------
// Allocation support
- // Allocate an object in new space. The object_size is specified
- // either in bytes or in words if the allocation flag SIZE_IN_WORDS
- // is passed. If the new space is exhausted control continues at the
- // gc_required label. The allocated object is returned in result. If
- // the flag tag_allocated_object is true the result is tagged as as
- // a heap object. All registers are clobbered also when control
- // continues at the gc_required label.
- void AllocateInNewSpace(int object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags);
+ // Allocate an object in new space or old pointer space. The object_size is
+ // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
+ // is passed. If the space is exhausted control continues at the gc_required
+ // label. The allocated object is returned in result. If the flag
+ // tag_allocated_object is true the result is tagged as as a heap object.
+ // All registers are clobbered also when control continues at the gc_required
+ // label.
+ void Allocate(int object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags);
+
void AllocateInNewSpace(Register object_size,
Register result,
Register scratch1,
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 7e6c344..0cb80c0 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -337,9 +337,6 @@
__ b(ne, &fail);
__ sub(r3, r3, Operand('a'));
__ cmp(r3, Operand('z' - 'a')); // Is r3 a lowercase letter?
-#ifndef ENABLE_LATIN_1
- __ b(hi, &fail);
-#else
__ b(ls, &loop_check); // In range 'a'-'z'.
// Latin-1: Check for values in range [224,254] but not 247.
__ sub(r3, r3, Operand(224 - 'a'));
@@ -347,7 +344,6 @@
__ b(hi, &fail); // Weren't Latin-1 letters.
__ cmp(r3, Operand(247 - 224)); // Check for 247.
__ b(eq, &fail);
-#endif
__ bind(&loop_check);
__ cmp(r0, r1);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index ac9b5ec..e3d27f1 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -320,19 +320,6 @@
}
-// Load a fast property out of a holder object (src). In-object properties
-// are loaded directly otherwise the property is loaded from the properties
-// fixed array.
-void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst,
- Register src,
- Handle<JSObject> holder,
- PropertyIndex index) {
- DoGenerateFastPropertyLoad(
- masm, dst, src, index.is_inobject(holder), index.translate(holder));
-}
-
-
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst,
Register src,
@@ -446,9 +433,11 @@
Handle<Name> name,
Register receiver_reg,
Register name_reg,
+ Register value_reg,
Register scratch1,
Register scratch2,
- Label* miss_label) {
+ Label* miss_label,
+ Label* miss_restore_name) {
// r0 : value
Label exit;
@@ -485,17 +474,8 @@
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- // We need an extra register, push
- __ push(name_reg);
- Label miss_pop, done_check;
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, &miss_pop);
- __ jmp(&done_check);
- __ bind(&miss_pop);
- __ pop(name_reg);
- __ jmp(miss_label);
- __ bind(&done_check);
- __ pop(name_reg);
+ scratch1, scratch2, name, miss_restore_name);
}
// Stub never generated for non-global objects that require access
@@ -542,14 +522,14 @@
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ str(r0, FieldMemOperand(receiver_reg, offset));
+ __ str(value_reg, FieldMemOperand(receiver_reg, offset));
// Skip updating write barrier if storing a smi.
- __ JumpIfSmi(r0, &exit);
+ __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address.
// Pass the now unused name_reg as a scratch register.
- __ mov(name_reg, r0);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
offset,
name_reg,
@@ -562,14 +542,14 @@
// Get the properties array
__ ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ str(r0, FieldMemOperand(scratch1, offset));
+ __ str(value_reg, FieldMemOperand(scratch1, offset));
// Skip updating write barrier if storing a smi.
- __ JumpIfSmi(r0, &exit);
+ __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address.
// Ok to clobber receiver_reg and name_reg, since we return.
- __ mov(name_reg, r0);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
offset,
name_reg,
@@ -579,26 +559,19 @@
}
// Return the value (register r0).
+ ASSERT(value_reg.is(r0));
__ bind(&exit);
__ Ret();
}
-void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
- Handle<Code> code = (kind == Code::LOAD_IC)
- ? masm->isolate()->builtins()->LoadIC_Miss()
- : masm->isolate()->builtins()->KeyedLoadIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
- Handle<Code> code = (kind == Code::STORE_IC)
- ? masm->isolate()->builtins()->StoreIC_Miss()
- : masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
+void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
+ Label* label,
+ Handle<Name> name) {
+ if (!label->is_unused()) {
+ __ bind(label);
+ __ mov(this->name(), Operand(name));
+ }
}
@@ -1063,15 +1036,15 @@
}
-#undef __
-#define __ ACCESS_MASM(masm())
-
-
-void StubCompiler::GenerateTailCall(Handle<Code> code) {
+void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
__ Jump(code, RelocInfo::CODE_TARGET);
}
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
@@ -1190,7 +1163,7 @@
if (!miss->is_unused()) {
__ b(success);
__ bind(miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
}
}
@@ -2599,58 +2572,23 @@
}
-Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
- Label miss;
-
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- r1, r2, r3, r4,
- &miss);
- __ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
Label miss;
// Check that the maps haven't changed.
- __ JumpIfSmi(r1, &miss);
- CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss);
+ __ JumpIfSmi(receiver(), &miss);
+ CheckPrototypes(object, receiver(), holder,
+ scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
- __ push(r1); // receiver
+ __ push(receiver()); // receiver
__ mov(ip, Operand(callback)); // callback info
- __ Push(ip, r2, r0);
+ __ Push(ip, this->name(), value());
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@@ -2660,11 +2598,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::CALLBACKS, name);
+ return GetICCode(kind(), Code::CALLBACKS, name);
}
@@ -2713,62 +2650,28 @@
#define __ ACCESS_MASM(masm())
-Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<Name> name,
- Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<JSFunction> setter) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
- Label miss;
-
- // Check that the maps haven't changed.
- __ JumpIfSmi(r1, &miss);
- CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss);
-
- GenerateStoreViaSetter(masm(), setter);
-
- __ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::CALLBACKS, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
- __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss,
+ __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
- if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(r1, r3, &miss);
+ if (object->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
}
// Stub is never generated for non-global objects that require access
// checks.
- ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- __ Push(r1, r2, r0); // Receiver, name, value.
+ __ Push(receiver(), this->name(), value());
- __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
- __ push(r0); // strict mode
+ __ mov(scratch1(), Operand(Smi::FromInt(strict_mode())));
+ __ push(scratch1()); // strict mode
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@@ -2778,11 +2681,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::INTERCEPTOR, name);
+ return GetICCode(kind(), Code::INTERCEPTOR, name);
}
@@ -2790,45 +2692,42 @@
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
- __ cmp(r3, Operand(Handle<Map>(object->map())));
+ __ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
+ __ cmp(scratch1(), Operand(Handle<Map>(object->map())));
__ b(ne, &miss);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
// to update the property details in the property dictionary of the
// global object. We bail out to the runtime system to do that.
- __ mov(r4, Operand(cell));
- __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
- __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
- __ cmp(r5, r6);
+ __ mov(scratch1(), Operand(cell));
+ __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
+ __ ldr(scratch3(),
+ FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+ __ cmp(scratch3(), scratch2());
__ b(eq, &miss);
// Store the value in the cell.
- __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
+ __ str(value(),
+ FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
// Cells are always rescanned, so no write barrier here.
Counters* counters = masm()->isolate()->counters();
- __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
+ __ IncrementCounter(
+ counters->named_store_global_inline(), 1, scratch1(), scratch2());
__ Ret();
// Handle store cache miss.
__ bind(&miss);
- __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ __ IncrementCounter(
+ counters->named_store_global_inline_miss(), 1, scratch1(), scratch2());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, name);
+ return GetICCode(kind(), Code::NORMAL, name);
}
@@ -2866,6 +2765,20 @@
}
+Register* StoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { r1, r2, r0, r3, r4, r5 };
+ return registers;
+}
+
+
+Register* KeyedStoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { r2, r1, r0, r3, r4, r5 };
+ return registers;
+}
+
+
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
@@ -2874,6 +2787,14 @@
}
+void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss) {
+ __ cmp(name_reg, Operand(name));
+ __ b(ne, miss);
+}
+
+
#undef __
#define __ ACCESS_MASM(masm)
@@ -2948,34 +2869,6 @@
}
-Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- lr : return address
- // -- r0 : key
- // -- r1 : receiver
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
- Handle<Code> stub = KeyedLoadFastElementStub(
- receiver_map->instance_type() == JS_ARRAY_TYPE,
- elements_kind).GetCode(isolate());
- __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
- } else {
- Handle<Code> stub =
- KeyedLoadDictionaryElementStub().GetCode(isolate());
- __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK);
- }
-
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
@@ -3000,7 +2893,7 @@
}
__ bind(&miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
InlineCacheState state =
@@ -3009,109 +2902,35 @@
}
-Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : name
- // -- r2 : receiver
- // -- lr : return address
- // -----------------------------------
- Label miss;
-
- Counters* counters = masm()->isolate()->counters();
- __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4);
-
- // Check that the name has not changed.
- __ cmp(r1, Operand(name));
- __ b(ne, &miss);
-
- // r3 is used as scratch register. r1 and r2 keep their values if a jump to
- // the miss label is generated.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- r2, r1, r3, r4,
- &miss);
- __ bind(&miss);
-
- __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
- Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : key
- // -- r2 : receiver
- // -- lr : return address
- // -- r3 : scratch
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
- Handle<Code> stub =
- KeyedStoreElementStub(is_js_array,
- elements_kind,
- store_mode_).GetCode(isolate());
-
- __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
-
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : key
- // -- r2 : receiver
- // -- lr : return address
- // -- r3 : scratch
- // -----------------------------------
Label miss;
- __ JumpIfSmi(r2, &miss);
+ __ JumpIfSmi(receiver(), &miss);
int receiver_count = receiver_maps->length();
- __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+ __ ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_count; ++i) {
__ mov(ip, Operand(receiver_maps->at(i)));
- __ cmp(r3, ip);
+ __ cmp(scratch1(), ip);
if (transitioned_maps->at(i).is_null()) {
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq);
} else {
Label next_map;
__ b(ne, &next_map);
- __ mov(r3, Operand(transitioned_maps->at(i)));
+ __ mov(transition_map(), Operand(transitioned_maps->at(i)));
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al);
__ bind(&next_map);
}
}
__ bind(&miss);
- Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
+ return GetICCode(
+ kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
}
@@ -3292,9 +3111,7 @@
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedLoadIC_Slow();
- __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
// Miss case, call the runtime.
__ bind(&miss_force_generic);
@@ -3304,10 +3121,7 @@
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
-
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
}
@@ -3699,9 +3513,7 @@
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
// Miss case, call the runtime.
__ bind(&miss_force_generic);
@@ -3711,10 +3523,7 @@
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
-
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
}
@@ -3807,13 +3616,10 @@
__ Ret();
__ bind(&miss_force_generic);
- Handle<Code> ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -3833,8 +3639,7 @@
__ b(ne, &check_capacity);
int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
- TAG_OBJECT);
+ __ Allocate(size, elements_reg, scratch, scratch2, &slow, TAG_OBJECT);
__ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
__ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
@@ -3878,8 +3683,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
@@ -3953,13 +3757,10 @@
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
- Handle<Code> ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -3987,8 +3788,7 @@
__ b(ne, &check_capacity);
int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
- TAG_OBJECT);
+ __ Allocate(size, elements_reg, scratch1, scratch2, &slow, TAG_OBJECT);
// Initialize the new FixedDoubleArray.
__ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
@@ -4044,8 +3844,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
diff --git a/src/assembler.cc b/src/assembler.cc
index 8d8208d..fc96662 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -811,7 +811,7 @@
}
} else if (IsPosition(rmode_)) {
PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
- } else if (rmode_ == RelocInfo::RUNTIME_ENTRY &&
+ } else if (IsRuntimeEntry(rmode_) &&
Isolate::Current()->deoptimizer_data() != NULL) {
// Depotimization bailouts are stored as runtime entries.
int id = Deoptimizer::GetDeoptimizationId(
@@ -1188,6 +1188,20 @@
}
+ExternalReference ExternalReference::old_pointer_space_allocation_top_address(
+ Isolate* isolate) {
+ return ExternalReference(
+ isolate->heap()->OldPointerSpaceAllocationTopAddress());
+}
+
+
+ExternalReference ExternalReference::old_pointer_space_allocation_limit_address(
+ Isolate* isolate) {
+ return ExternalReference(
+ isolate->heap()->OldPointerSpaceAllocationLimitAddress());
+}
+
+
ExternalReference ExternalReference::handle_scope_level_address(
Isolate* isolate) {
return ExternalReference(HandleScope::current_level_address(isolate));
diff --git a/src/assembler.h b/src/assembler.h
index f5ae611..4a67ce3 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -373,7 +373,7 @@
// Read/modify the code target in the branch/call instruction
// this relocation applies to;
- // can only be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
+ // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
INLINE(Address target_address());
INLINE(void set_target_address(Address target,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
@@ -749,6 +749,10 @@
// Used for fast allocation in generated code.
static ExternalReference new_space_allocation_top_address(Isolate* isolate);
static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
+ static ExternalReference old_pointer_space_allocation_top_address(
+ Isolate* isolate);
+ static ExternalReference old_pointer_space_allocation_limit_address(
+ Isolate* isolate);
static ExternalReference double_fp_operation(Token::Value operation,
Isolate* isolate);
diff --git a/src/ast.cc b/src/ast.cc
index 02c815c..712bfd1 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -1007,11 +1007,6 @@
add_flag(kDontInline); \
add_flag(kDontSelfOptimize); \
}
-#define DONT_INLINE_NODE(NodeType) \
- void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
- increase_node_count(); \
- add_flag(kDontInline); \
- }
#define DONT_SELFOPTIMIZE_NODE(NodeType) \
void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
increase_node_count(); \
@@ -1038,8 +1033,10 @@
REGULAR_NODE(SwitchStatement)
REGULAR_NODE(Conditional)
REGULAR_NODE(Literal)
+REGULAR_NODE(ArrayLiteral)
REGULAR_NODE(ObjectLiteral)
REGULAR_NODE(RegExpLiteral)
+REGULAR_NODE(FunctionLiteral)
REGULAR_NODE(Assignment)
REGULAR_NODE(Throw)
REGULAR_NODE(Property)
@@ -1070,9 +1067,6 @@
DONT_OPTIMIZE_NODE(DebuggerStatement)
DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)
-DONT_INLINE_NODE(ArrayLiteral) // TODO(1322): Allow materialized literals.
-DONT_INLINE_NODE(FunctionLiteral)
-
DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
DONT_SELFOPTIMIZE_NODE(WhileStatement)
DONT_SELFOPTIMIZE_NODE(ForStatement)
@@ -1099,7 +1093,6 @@
#undef REGULAR_NODE
#undef DONT_OPTIMIZE_NODE
-#undef DONT_INLINE_NODE
#undef DONT_SELFOPTIMIZE_NODE
#undef DONT_CACHE_NODE
diff --git a/src/builtins.cc b/src/builtins.cc
index aa69203..f8d562b 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -203,12 +203,6 @@
holey = (value > 0 && value < JSObject::kInitialMaxFastElementArray);
}
- ASSERT(function->has_initial_map());
- ElementsKind kind = function->initial_map()->elements_kind();
- if (holey) {
- kind = GetHoleyElementsKind(kind);
- }
-
MaybeObject* maybe_array;
if (*type_info != isolate->heap()->undefined_value()) {
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(*type_info);
@@ -224,14 +218,20 @@
AllocationSiteMode mode = AllocationSiteInfo::GetMode(to_kind);
if (mode == TRACK_ALLOCATION_SITE) {
maybe_array = isolate->heap()->AllocateEmptyJSArrayWithAllocationSite(
- kind, type_info);
+ to_kind, type_info);
} else {
- maybe_array = isolate->heap()->AllocateEmptyJSArray(kind);
+ maybe_array = isolate->heap()->AllocateEmptyJSArray(to_kind);
}
if (!maybe_array->To(&array)) return maybe_array;
}
}
+ ASSERT(function->has_initial_map());
+ ElementsKind kind = function->initial_map()->elements_kind();
+ if (holey) {
+ kind = GetHoleyElementsKind(kind);
+ }
+
if (array == NULL) {
maybe_array = isolate->heap()->AllocateEmptyJSArray(kind);
if (!maybe_array->To(&array)) return maybe_array;
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index bb8bfe3..ae198bc 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -39,7 +39,7 @@
Isolate* isolate = graph->isolate();
AssertNoAllocation no_gc;
NoHandleAllocation no_handles(isolate);
- NoHandleDereference no_deref(isolate);
+ HandleDereferenceGuard no_deref(isolate, HandleDereferenceGuard::DISALLOW);
ASSERT(graph != NULL);
SmartArrayPointer<char> bailout_reason;
@@ -189,11 +189,16 @@
HValue* size_in_bytes =
AddInstruction(new(zone) HConstant(size, Representation::Integer32()));
+ HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
+ if (FLAG_pretenure_literals) {
+ flags = static_cast<HAllocate::Flags>(
+ flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
+ }
HInstruction* object =
AddInstruction(new(zone) HAllocate(context(),
size_in_bytes,
HType::JSObject(),
- HAllocate::CAN_ALLOCATE_IN_NEW_SPACE));
+ flags));
for (int i = 0; i < size; i += kPointerSize) {
HInstruction* value =
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 151a51c..e91b241 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -149,10 +149,10 @@
virtual ~CodeStub() {}
- bool CompilingCallsToThisStubIsGCSafe() {
+ bool CompilingCallsToThisStubIsGCSafe(Isolate* isolate) {
bool is_pregenerated = IsPregenerated();
Code* code = NULL;
- CHECK(!is_pregenerated || FindCodeInCache(&code, Isolate::Current()));
+ CHECK(!is_pregenerated || FindCodeInCache(&code, isolate));
return is_pregenerated;
}
diff --git a/src/compiler.cc b/src/compiler.cc
index 8f4be0c..e51fb42 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -396,7 +396,7 @@
OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
AssertNoAllocation no_gc;
NoHandleAllocation no_handles(isolate());
- NoHandleDereference no_deref(isolate());
+ HandleDereferenceGuard no_deref(isolate(), HandleDereferenceGuard::DISALLOW);
ASSERT(last_status() == SUCCEEDED);
Timer t(this, &time_taken_to_optimize_);
@@ -943,7 +943,9 @@
new(info->zone()) OptimizingCompiler(*info);
OptimizingCompiler::Status status = compiler->CreateGraph();
if (status == OptimizingCompiler::SUCCEEDED) {
- closure->MarkInRecompileQueue();
+ // Do a scavenge to put off the next scavenge as far as possible.
+ // This may ease the issue that GVN blocks the next scavenge.
+ isolate->heap()->CollectGarbage(NEW_SPACE, "parallel recompile");
shared->code()->set_profiler_ticks(0);
info.Detach();
isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
@@ -975,7 +977,19 @@
void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
SmartPointer<CompilationInfo> info(optimizing_compiler->info());
- ASSERT(info->closure()->IsMarkedForInstallingRecompiledCode());
+ // 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()));
+ InstallFullCode(*info);
+ if (FLAG_trace_parallel_recompilation) {
+ PrintF(" ** aborting optimization for ");
+ info->closure()->PrintName();
+ PrintF(" as it has been disabled.\n");
+ }
+ ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
+ return;
+ }
Isolate* isolate = info->isolate();
VMState state(isolate, PARALLEL_COMPILER);
@@ -1015,6 +1029,7 @@
// Optimized code is finally replacing unoptimized code. Reset the latter's
// profiler ticks to prevent too soon re-opt after a deopt.
info->shared_info()->code()->set_profiler_ticks(0);
+ ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
}
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index f044328..a20de43 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -54,7 +54,9 @@
Handle<Object> exec_state,
Handle<Object> event_data,
Handle<Value> data) {
- HandleScope scope;
+ // TODO(svenpanne) There should be a way to retrieve this in the callback.
+ Isolate* isolate = Isolate::GetCurrent();
+ HandleScope scope(isolate);
// Check for handled event.
if (event != Break && event != Exception && event != AfterCompile) {
@@ -69,7 +71,7 @@
Function::Cast(*event_data->Get(to_json_fun_name));
Local<Value> event_json = to_json_fun->Call(event_data, 0, NULL);
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
return;
}
@@ -77,7 +79,7 @@
Handle<Object> details =
Shell::DebugMessageDetails(Handle<String>::Cast(event_json));
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
return;
}
String::Utf8Value str(details->Get(String::New("text")));
@@ -93,7 +95,7 @@
Local<Object> cmd_processor =
Object::Cast(*fun->Call(exec_state, 0, NULL));
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
return;
}
@@ -114,7 +116,7 @@
Handle<Value> request =
Shell::DebugCommandToJSONRequest(String::New(command));
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
continue;
}
@@ -138,7 +140,7 @@
args[0] = request;
Handle<Value> response_val = fun->Call(cmd_processor, kArgc, args);
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
continue;
}
Handle<String> response = Handle<String>::Cast(response_val);
@@ -146,7 +148,7 @@
// Convert the debugger response into text details and the running state.
Handle<Object> response_details = Shell::DebugMessageDetails(response);
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate, &try_catch);
continue;
}
String::Utf8Value text_str(response_details->Get(String::New("text")));
@@ -159,8 +161,8 @@
}
-void RunRemoteDebugger(int port) {
- RemoteDebugger debugger(port);
+void RunRemoteDebugger(Isolate* isolate, int port) {
+ RemoteDebugger debugger(isolate, port);
debugger.Run();
}
@@ -273,15 +275,15 @@
void RemoteDebugger::HandleMessageReceived(char* message) {
- Locker lock(v8::Isolate::GetCurrent());
- HandleScope scope;
+ Locker lock(isolate_);
+ HandleScope scope(isolate_);
// Print the event details.
TryCatch try_catch;
Handle<Object> details =
Shell::DebugMessageDetails(Handle<String>::Cast(String::New(message)));
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate_, &try_catch);
PrintPrompt();
return;
}
@@ -302,15 +304,15 @@
void RemoteDebugger::HandleKeyboardCommand(char* command) {
- Locker lock(v8::Isolate::GetCurrent());
- HandleScope scope;
+ Locker lock(isolate_);
+ HandleScope scope(isolate_);
// Convert the debugger command to a JSON debugger request.
TryCatch try_catch;
Handle<Value> request =
Shell::DebugCommandToJSONRequest(String::New(command));
if (try_catch.HasCaught()) {
- Shell::ReportException(&try_catch);
+ Shell::ReportException(isolate_, &try_catch);
PrintPrompt();
return;
}
diff --git a/src/d8-debug.h b/src/d8-debug.h
index aeff3c1..a6cea2a 100644
--- a/src/d8-debug.h
+++ b/src/d8-debug.h
@@ -43,7 +43,7 @@
// Start the remove debugger connecting to a V8 debugger agent on the specified
// port.
-void RunRemoteDebugger(int port);
+void RunRemoteDebugger(Isolate* isolate, int port);
// Forward declerations.
class RemoteDebuggerEvent;
@@ -53,8 +53,9 @@
// Remote debugging class.
class RemoteDebugger {
public:
- explicit RemoteDebugger(int port)
- : port_(port),
+ explicit RemoteDebugger(Isolate* isolate, int port)
+ : isolate_(isolate),
+ port_(port),
event_access_(i::OS::CreateMutex()),
event_available_(i::OS::CreateSemaphore(0)),
head_(NULL), tail_(NULL) {}
@@ -79,6 +80,7 @@
// Get connection to agent in debugged V8.
i::Socket* conn() { return conn_; }
+ Isolate* isolate_;
int port_; // Port used to connect to debugger V8.
i::Socket* conn_; // Connection to debugger agent in debugged V8.
diff --git a/src/d8-posix.cc b/src/d8-posix.cc
index 8a278e4..1be782a 100644
--- a/src/d8-posix.cc
+++ b/src/d8-posix.cc
@@ -449,7 +449,7 @@
// Implementation of the system() function (see d8.h for details).
Handle<Value> Shell::System(const Arguments& args) {
- HandleScope scope;
+ HandleScope scope(args.GetIsolate());
int read_timeout = -1;
int total_timeout = -1;
if (!GetTimeouts(args, &read_timeout, &total_timeout)) return v8::Undefined();
diff --git a/src/d8-readline.cc b/src/d8-readline.cc
index cc7a3a6..5226364 100644
--- a/src/d8-readline.cc
+++ b/src/d8-readline.cc
@@ -154,7 +154,7 @@
HandleScope scope;
Local<String> full_text = String::New(rl_line_buffer, rl_point);
Handle<Array> completions =
- Shell::GetCompletions(String::New(text), full_text);
+ Shell::GetCompletions(isolate, String::New(text), full_text);
current_completions = Persistent<Array>::New(isolate, completions);
current_index = 0;
}
diff --git a/src/d8.cc b/src/d8.cc
index 24c89e9..eaebd90 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -93,7 +93,7 @@
class Symbols {
public:
explicit Symbols(Isolate* isolate) : isolate_(isolate) {
- HandleScope scope;
+ HandleScope scope(isolate);
#define INIT_SYMBOL(name, value) \
name##_ = Persistent<String>::New(isolate, String::NewSymbol(value));
FOR_EACH_SYMBOL(INIT_SYMBOL)
@@ -181,7 +181,8 @@
// Executes a string within the current v8 context.
-bool Shell::ExecuteString(Handle<String> source,
+bool Shell::ExecuteString(Isolate* isolate,
+ Handle<String> source,
Handle<Value> name,
bool print_result,
bool report_exceptions) {
@@ -190,7 +191,7 @@
#else
bool FLAG_debugger = false;
#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
- HandleScope handle_scope;
+ HandleScope handle_scope(isolate);
TryCatch try_catch;
options.script_executed = true;
if (FLAG_debugger) {
@@ -201,7 +202,7 @@
if (script.IsEmpty()) {
// Print errors that happened during compilation.
if (report_exceptions && !FLAG_debugger)
- ReportException(&try_catch);
+ ReportException(isolate, &try_catch);
return false;
} else {
Handle<Value> result = script->Run();
@@ -209,7 +210,7 @@
ASSERT(try_catch.HasCaught());
// Print errors that happened during execution.
if (report_exceptions && !FLAG_debugger)
- ReportException(&try_catch);
+ ReportException(isolate, &try_catch);
return false;
} else {
ASSERT(!try_catch.HasCaught());
@@ -237,7 +238,7 @@
Handle<Value> Shell::Write(const Arguments& args) {
for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
+ HandleScope handle_scope(args.GetIsolate());
if (i != 0) {
printf(" ");
}
@@ -315,7 +316,7 @@
Handle<Value> Shell::Load(const Arguments& args) {
for (int i = 0; i < args.Length(); i++) {
- HandleScope handle_scope;
+ HandleScope handle_scope(args.GetIsolate());
String::Utf8Value file(args[i]);
if (*file == NULL) {
return Throw("Error loading file");
@@ -324,7 +325,11 @@
if (source.IsEmpty()) {
return Throw("Error loading file");
}
- if (!ExecuteString(source, String::New(*file), false, true)) {
+ if (!ExecuteString(args.GetIsolate(),
+ source,
+ String::New(*file),
+ false,
+ true)) {
return Throw("Error executing file");
}
}
@@ -389,7 +394,7 @@
Persistent<Object>::New(isolate, buffer);
persistent_array.MakeWeak(isolate, data, ExternalArrayWeakCallback);
persistent_array.MarkIndependent(isolate);
- V8::AdjustAmountOfExternalAllocatedMemory(length);
+ isolate->AdjustAmountOfExternalAllocatedMemory(length);
buffer->SetIndexedPropertiesToExternalArrayData(
data, v8::kExternalByteArray, length);
@@ -827,10 +832,10 @@
void Shell::ExternalArrayWeakCallback(v8::Isolate* isolate,
Persistent<Value> object,
void* data) {
- HandleScope scope;
+ HandleScope scope(isolate);
int32_t length =
object->ToObject()->Get(Symbols::byteLength(isolate))->Uint32Value();
- V8::AdjustAmountOfExternalAllocatedMemory(-length);
+ isolate->AdjustAmountOfExternalAllocatedMemory(-length);
delete[] static_cast<uint8_t*>(data);
object.Dispose(isolate);
}
@@ -903,8 +908,8 @@
}
-void Shell::ReportException(v8::TryCatch* try_catch) {
- HandleScope handle_scope;
+void Shell::ReportException(Isolate* isolate, v8::TryCatch* try_catch) {
+ HandleScope handle_scope(isolate);
#if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
bool enter_context = !Context::InContext();
if (enter_context) utility_context_->Enter();
@@ -950,8 +955,10 @@
#ifndef V8_SHARED
-Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
- HandleScope handle_scope;
+Handle<Array> Shell::GetCompletions(Isolate* isolate,
+ Handle<String> text,
+ Handle<String> full) {
+ HandleScope handle_scope(isolate);
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();
Handle<Value> fun = global->Get(String::New("GetCompletions"));
@@ -1094,7 +1101,7 @@
void Shell::InstallUtilityScript(Isolate* isolate) {
Locker lock(isolate);
- HandleScope scope;
+ HandleScope scope(isolate);
// If we use the utility context, we have to set the security tokens so that
// utility, evaluation and debug context can all access each other.
utility_context_->SetSecurityToken(Undefined(isolate));
@@ -1272,7 +1279,7 @@
if (options.test_shell) return;
#ifndef V8_SHARED
Locker lock(isolate);
- HandleScope scope;
+ HandleScope scope(isolate);
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
utility_context_ = Context::New(NULL, global_template);
@@ -1446,7 +1453,7 @@
Persistent<Object>::New(isolate, buffer);
persistent_buffer.MakeWeak(isolate, data, ExternalArrayWeakCallback);
persistent_buffer.MarkIndependent(isolate);
- V8::AdjustAmountOfExternalAllocatedMemory(length);
+ isolate->AdjustAmountOfExternalAllocatedMemory(length);
buffer->SetIndexedPropertiesToExternalArrayData(
data, kExternalUnsignedByteArray, length);
@@ -1493,16 +1500,16 @@
void Shell::RunShell(Isolate* isolate) {
Locker locker(isolate);
Context::Scope context_scope(evaluation_context_);
- HandleScope outer_scope;
+ HandleScope outer_scope(isolate);
Handle<String> name = String::New("(d8)");
LineEditor* console = LineEditor::Get();
printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name());
console->Open(isolate);
while (true) {
- HandleScope inner_scope;
+ HandleScope inner_scope(isolate);
Handle<String> input = console->Prompt(Shell::kPrompt);
if (input.IsEmpty()) break;
- ExecuteString(input, name, true, true);
+ ExecuteString(isolate, input, name, true, true);
}
printf("\n");
}
@@ -1541,13 +1548,13 @@
// Prepare the context for this thread.
Locker locker(isolate_);
- HandleScope outer_scope;
+ HandleScope outer_scope(isolate_);
Persistent<Context> thread_context =
Shell::CreateEvaluationContext(isolate_);
Context::Scope context_scope(thread_context);
while ((ptr != NULL) && (*ptr != '\0')) {
- HandleScope inner_scope;
+ HandleScope inner_scope(isolate_);
char* filename = ptr;
ptr = ReadWord(ptr);
@@ -1562,7 +1569,7 @@
Shell::Exit(1);
}
- Shell::ExecuteString(str, String::New(filename), false, false);
+ Shell::ExecuteString(isolate_, str, String::New(filename), false, false);
}
thread_context.Dispose(thread_context->GetIsolate());
@@ -1589,10 +1596,10 @@
const char* arg = argv_[i];
if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
// Execute argument given to -e option directly.
- HandleScope handle_scope;
+ HandleScope handle_scope(isolate);
Handle<String> file_name = String::New("unnamed");
Handle<String> source = String::New(argv_[i + 1]);
- if (!Shell::ExecuteString(source, file_name, false, true)) {
+ if (!Shell::ExecuteString(isolate, source, file_name, false, true)) {
Shell::Exit(1);
}
++i;
@@ -1600,14 +1607,14 @@
// Ignore other options. They have been parsed already.
} else {
// Use all other arguments as names of files to load and run.
- HandleScope handle_scope;
+ HandleScope handle_scope(isolate);
Handle<String> file_name = String::New(arg);
Handle<String> source = ReadFile(isolate, arg);
if (source.IsEmpty()) {
printf("Error reading '%s'\n", arg);
Shell::Exit(1);
}
- if (!Shell::ExecuteString(source, file_name, false, true)) {
+ if (!Shell::ExecuteString(isolate, source, file_name, false, true)) {
Shell::Exit(1);
}
}
@@ -1642,7 +1649,7 @@
{
Isolate::Scope iscope(isolate);
Locker lock(isolate);
- HandleScope scope;
+ HandleScope scope(isolate);
Symbols symbols(isolate);
Persistent<Context> context = Shell::CreateEvaluationContext(isolate);
{
@@ -1840,7 +1847,7 @@
#endif // V8_SHARED
{ // NOLINT
Locker lock(isolate);
- HandleScope scope;
+ HandleScope scope(isolate);
Persistent<Context> context = CreateEvaluationContext(isolate);
if (options.last_run) {
// Keep using the same context in the interactive shell.
@@ -1936,7 +1943,7 @@
// Run remote debugger if requested, but never on --test
if (i::FLAG_remote_debugger && !options.test_shell) {
InstallUtilityScript(isolate);
- RunRemoteDebugger(i::FLAG_debugger_port);
+ RunRemoteDebugger(isolate, i::FLAG_debugger_port);
return 0;
}
#endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT
diff --git a/src/d8.h b/src/d8.h
index 04c5454..621ac74 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -265,12 +265,13 @@
#endif // V8_SHARED
public:
- static bool ExecuteString(Handle<String> source,
+ static bool ExecuteString(Isolate* isolate,
+ Handle<String> source,
Handle<Value> name,
bool print_result,
bool report_exceptions);
static const char* ToCString(const v8::String::Utf8Value& value);
- static void ReportException(TryCatch* try_catch);
+ static void ReportException(Isolate* isolate, TryCatch* try_catch);
static Handle<String> ReadFile(Isolate* isolate, const char* name);
static Persistent<Context> CreateEvaluationContext(Isolate* isolate);
static int RunMain(Isolate* isolate, int argc, char* argv[]);
@@ -279,7 +280,8 @@
static void OnExit();
#ifndef V8_SHARED
- static Handle<Array> GetCompletions(Handle<String> text,
+ static Handle<Array> GetCompletions(Isolate* isolate,
+ Handle<String> text,
Handle<String> full);
static int* LookupCounter(const char* name);
static void* CreateHistogram(const char* name,
diff --git a/src/debug.cc b/src/debug.cc
index 2821578..1fd3e40 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3567,7 +3567,8 @@
v8::Handle<v8::String> MessageImpl::GetJSON() const {
- v8::HandleScope scope;
+ v8::HandleScope scope(
+ reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
if (IsEvent()) {
// Call toJSONProtocol on the debug event object.
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 5d18d68..3830759 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -282,7 +282,7 @@
if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
out.AddFormatted(" (id = %d)", static_cast<int>(relocinfo.data()));
}
- } else if (rmode == RelocInfo::RUNTIME_ENTRY &&
+ } else if (RelocInfo::IsRuntimeEntry(rmode) &&
isolate->deoptimizer_data() != NULL) {
// A runtime entry reloinfo might be a deoptimization bailout.
Address addr = relocinfo.target_address();
diff --git a/src/execution.h b/src/execution.h
index c350805..b104180 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -189,8 +189,6 @@
void Interrupt();
bool IsTerminateExecution();
void TerminateExecution();
- bool IsCodeReadyEvent();
- void RequestCodeReadyEvent();
#ifdef ENABLE_DEBUGGER_SUPPORT
bool IsDebugBreak();
void DebugBreak();
diff --git a/src/factory.cc b/src/factory.cc
index 9135d54..fece9a0 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -703,9 +703,11 @@
}
-Handle<Object> Factory::NewError(const char* maker, const char* type,
- Vector< Handle<Object> > args) {
- v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
+Handle<Object> Factory::NewError(const char* maker,
+ const char* type,
+ Vector< Handle<Object> > args) {
+ // Instantiate a closeable HandleScope for EscapeFrom.
+ v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate()));
Handle<FixedArray> array = NewFixedArray(args.length());
for (int i = 0; i < args.length(); i++) {
array->set(i, *args[i]);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 3a2426b..c4b560b 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -166,6 +166,7 @@
DEFINE_bool(clever_optimizations,
true,
"Optimize object size, Array shift, DOM strings and string +")
+DEFINE_bool(pretenure_literals, false, "allocate literals in old space")
// Flags for data representation optimizations
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
diff --git a/src/flags.cc b/src/flags.cc
index bca0eff..ff725ad 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -542,6 +542,7 @@
void FlagList::EnforceFlagImplications() {
#define FLAG_MODE_DEFINE_IMPLICATIONS
#include "flag-definitions.h"
+#undef FLAG_MODE_DEFINE_IMPLICATIONS
}
} } // namespace v8::internal
diff --git a/src/handles-inl.h b/src/handles-inl.h
index c1daae2..fd60a35 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -52,10 +52,26 @@
template <typename T>
+inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
+ ASSERT(location_ == NULL ||
+ reinterpret_cast<Address>(*location_) != kZapValue);
+#ifdef DEBUG
+ if (FLAG_enable_slow_asserts) {
+ Isolate* isolate = Isolate::Current();
+ CHECK(isolate->AllowHandleDereference() ||
+ Heap::RelocationLock::IsLocked(isolate->heap()) ||
+ !isolate->optimizing_compiler_thread()->IsOptimizerThread());
+ }
+#endif // DEBUG
+ return *location_ == *other.location_;
+}
+
+
+template <typename T>
inline T* Handle<T>::operator*() const {
ASSERT(location_ != NULL);
ASSERT(reinterpret_cast<Address>(*location_) != kHandleZapValue);
- SLOW_ASSERT(ISOLATE->allow_handle_deref());
+ SLOW_ASSERT(Isolate::Current()->AllowHandleDereference());
return *BitCast<T**>(location_);
}
@@ -63,7 +79,7 @@
inline T** Handle<T>::location() const {
ASSERT(location_ == NULL ||
reinterpret_cast<Address>(*location_) != kZapValue);
- SLOW_ASSERT(ISOLATE->allow_handle_deref());
+ SLOW_ASSERT(Isolate::Current()->AllowHandleDereference());
return location_;
}
@@ -164,39 +180,19 @@
}
-NoHandleDereference::NoHandleDereference(Isolate* isolate)
+HandleDereferenceGuard::HandleDereferenceGuard(Isolate* isolate, State state)
: isolate_(isolate) {
- // The guard is set on a per-isolate basis, so it affects all threads.
- // That's why we can only use it when running without parallel recompilation.
- if (FLAG_parallel_recompilation) return;
- old_state_ = isolate->allow_handle_deref();
- isolate_->set_allow_handle_deref(false);
+ old_state_ = isolate_->AllowHandleDereference();
+ isolate_->SetAllowHandleDereference(state == ALLOW);
}
-NoHandleDereference::~NoHandleDereference() {
- if (FLAG_parallel_recompilation) return;
- isolate_->set_allow_handle_deref(old_state_);
+HandleDereferenceGuard::~HandleDereferenceGuard() {
+ isolate_->SetAllowHandleDereference(old_state_);
}
-
-AllowHandleDereference::AllowHandleDereference(Isolate* isolate)
- : isolate_(isolate) {
- // The guard is set on a per-isolate basis, so it affects all threads.
- // That's why we can only use it when running without parallel recompilation.
- if (FLAG_parallel_recompilation) return;
- old_state_ = isolate->allow_handle_deref();
- isolate_->set_allow_handle_deref(true);
-}
-
-
-AllowHandleDereference::~AllowHandleDereference() {
- if (FLAG_parallel_recompilation) return;
- isolate_->set_allow_handle_deref(old_state_);
-}
#endif
-
} } // namespace v8::internal
#endif // V8_HANDLES_INL_H_
diff --git a/src/handles.h b/src/handles.h
index b0b271c..3e408b7 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -64,9 +64,7 @@
INLINE(T* operator ->() const) { return operator*(); }
// Check if this handle refers to the exact same object as the other handle.
- bool is_identical_to(const Handle<T> other) const {
- return *location_ == *other.location_;
- }
+ INLINE(bool is_identical_to(const Handle<T> other) const);
// Provides the C++ dereference operator.
INLINE(T* operator*() const);
@@ -341,29 +339,15 @@
};
-class NoHandleDereference BASE_EMBEDDED {
+class HandleDereferenceGuard BASE_EMBEDDED {
public:
+ enum State { ALLOW, DISALLOW };
#ifndef DEBUG
- explicit NoHandleDereference(Isolate* isolate) {}
- ~NoHandleDereference() {}
+ HandleDereferenceGuard(Isolate* isolate, State state) { }
+ ~HandleDereferenceGuard() { }
#else
- explicit inline NoHandleDereference(Isolate* isolate);
- inline ~NoHandleDereference();
- private:
- Isolate* isolate_;
- bool old_state_;
-#endif
-};
-
-
-class AllowHandleDereference BASE_EMBEDDED {
- public:
-#ifndef DEBUG
- explicit AllowHandleDereference(Isolate* isolate) {}
- ~AllowHandleDereference() {}
-#else
- explicit inline AllowHandleDereference(Isolate* isolate);
- inline ~AllowHandleDereference();
+ inline HandleDereferenceGuard(Isolate* isolate, State state);
+ inline ~HandleDereferenceGuard();
private:
Isolate* isolate_;
bool old_state_;
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 3644876..9ed65d8 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -653,24 +653,12 @@
// TODO(yangguo): check that the object is indeed an external string.
ASSERT(heap_->InNewSpace(obj));
ASSERT(obj != HEAP->the_hole_value());
-#ifndef ENABLE_LATIN_1
- if (obj->IsExternalAsciiString()) {
- ExternalAsciiString* string = ExternalAsciiString::cast(obj);
- ASSERT(String::IsAscii(string->GetChars(), string->length()));
- }
-#endif
}
for (int i = 0; i < old_space_strings_.length(); ++i) {
Object* obj = Object::cast(old_space_strings_[i]);
// TODO(yangguo): check that the object is indeed an external string.
ASSERT(!heap_->InNewSpace(obj));
ASSERT(obj != HEAP->the_hole_value());
-#ifndef ENABLE_LATIN_1
- if (obj->IsExternalAsciiString()) {
- ExternalAsciiString* string = ExternalAsciiString::cast(obj);
- ASSERT(String::IsAscii(string->GetChars(), string->length()));
- }
-#endif
}
#endif
}
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 5f46678..cdd5a07 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -174,6 +174,7 @@
case kHeapNumber: return "/number/";
case kNative: return "/native/";
case kSynthetic: return "/synthetic/";
+ case kContext: return "/context/";
default: return "???";
}
}
@@ -826,7 +827,7 @@
} else if (object->IsNativeContext()) {
return AddEntry(object, HeapEntry::kHidden, "system / NativeContext");
} else if (object->IsContext()) {
- return AddEntry(object, HeapEntry::kHidden, "system / Context");
+ return AddEntry(object, HeapEntry::kContext, "system / Context");
} else if (object->IsFixedArray() ||
object->IsFixedDoubleArray() ||
object->IsByteArray() ||
@@ -1097,6 +1098,27 @@
void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
+ if (context == context->declaration_context()) {
+ ScopeInfo* scope_info = context->closure()->shared()->scope_info();
+ // Add context allocated locals.
+ int context_locals = scope_info->ContextLocalCount();
+ for (int i = 0; i < context_locals; ++i) {
+ String* local_name = scope_info->ContextLocalName(i);
+ int idx = Context::MIN_CONTEXT_SLOTS + i;
+ SetContextReference(context, entry, local_name, context->get(idx),
+ Context::OffsetOfElementAt(idx));
+ }
+ if (scope_info->HasFunctionName()) {
+ String* name = scope_info->FunctionName();
+ VariableMode mode;
+ int idx = scope_info->FunctionContextSlotIndex(name, &mode);
+ if (idx >= 0) {
+ SetContextReference(context, entry, name, context->get(idx),
+ Context::OffsetOfElementAt(idx));
+ }
+ }
+ }
+
#define EXTRACT_CONTEXT_FIELD(index, type, name) \
SetInternalReference(context, entry, #name, context->get(Context::index), \
FixedArray::OffsetOfElementAt(Context::index));
@@ -1286,26 +1308,6 @@
SetNativeBindReference(js_obj, entry, reference_name,
bindings->get(i));
}
- } else {
- Context* context = func->context()->declaration_context();
- ScopeInfo* scope_info = context->closure()->shared()->scope_info();
- // Add context allocated locals.
- int context_locals = scope_info->ContextLocalCount();
- for (int i = 0; i < context_locals; ++i) {
- String* local_name = scope_info->ContextLocalName(i);
- int idx = Context::MIN_CONTEXT_SLOTS + i;
- SetClosureReference(js_obj, entry, local_name, context->get(idx));
- }
-
- // Add function variable.
- if (scope_info->HasFunctionName()) {
- String* name = scope_info->FunctionName();
- VariableMode mode;
- int idx = scope_info->FunctionContextSlotIndex(name, &mode);
- if (idx >= 0) {
- SetClosureReference(js_obj, entry, name, context->get(idx));
- }
- }
}
}
@@ -1580,16 +1582,18 @@
}
-void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
+void V8HeapExplorer::SetContextReference(HeapObject* parent_obj,
int parent_entry,
String* reference_name,
- Object* child_obj) {
+ Object* child_obj,
+ int field_offset) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
parent_entry,
collection_->names()->GetName(reference_name),
child_entry);
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
}
}
@@ -2576,7 +2580,8 @@
JSON_S("regexp") ","
JSON_S("number") ","
JSON_S("native") ","
- JSON_S("synthetic")) ","
+ JSON_S("synthetic") ","
+ JSON_S("context")) ","
JSON_S("string") ","
JSON_S("number") ","
JSON_S("number") ","
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index fe15715..c952381 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -98,7 +98,8 @@
kRegExp = v8::HeapGraphNode::kRegExp,
kHeapNumber = v8::HeapGraphNode::kHeapNumber,
kNative = v8::HeapGraphNode::kNative,
- kSynthetic = v8::HeapGraphNode::kSynthetic
+ kSynthetic = v8::HeapGraphNode::kSynthetic,
+ kContext = v8::HeapGraphNode::kContext
};
static const int kNoEntry;
@@ -479,10 +480,11 @@
void ExtractElementReferences(JSObject* js_obj, int entry);
void ExtractInternalReferences(JSObject* js_obj, int entry);
bool IsEssentialObject(Object* object);
- void SetClosureReference(HeapObject* parent_obj,
+ void SetContextReference(HeapObject* parent_obj,
int parent,
String* reference_name,
- Object* child);
+ Object* child,
+ int field_offset);
void SetNativeBindReference(HeapObject* parent_obj,
int parent,
const char* reference_name,
diff --git a/src/heap.cc b/src/heap.cc
index fe1783d..9ee64e3 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3596,10 +3596,6 @@
return Failure::OutOfMemoryException(0x5);
}
-#ifndef ENABLE_LATIN_1
- ASSERT(String::IsAscii(resource->data(), static_cast<int>(length)));
-#endif // ENABLE_LATIN_1
-
Map* map = external_ascii_string_map();
Object* result;
{ MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
@@ -5078,17 +5074,6 @@
String::cast(result)->set_hash_field(String::kEmptyHashField);
ASSERT_EQ(size, HeapObject::cast(result)->Size());
-#ifndef ENABLE_LATIN_1
-#ifdef VERIFY_HEAP
- if (FLAG_verify_heap) {
- // Initialize string's content to ensure ASCII-ness (character range 0-127)
- // as required when verifying the heap.
- uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
- memset(dest, 0x0F, length * kCharSize);
- }
-#endif
-#endif
-
return result;
}
@@ -6597,6 +6582,9 @@
store_buffer()->SetUp();
if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
+#ifdef DEBUG
+ relocation_mutex_locked_ = false;
+#endif // DEBUG
return true;
}
diff --git a/src/heap.h b/src/heap.h
index 456e9d8..d26c384 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -590,6 +590,13 @@
return new_space_.allocation_limit_address();
}
+ Address* OldPointerSpaceAllocationTopAddress() {
+ return old_pointer_space_->allocation_top_address();
+ }
+ Address* OldPointerSpaceAllocationLimitAddress() {
+ return old_pointer_space_->allocation_limit_address();
+ }
+
// Uncommit unused semi space.
bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); }
@@ -1822,14 +1829,27 @@
explicit RelocationLock(Heap* heap) : heap_(heap) {
if (FLAG_parallel_recompilation) {
heap_->relocation_mutex_->Lock();
+#ifdef DEBUG
+ heap_->relocation_mutex_locked_ = true;
+#endif // DEBUG
}
}
+
~RelocationLock() {
if (FLAG_parallel_recompilation) {
+#ifdef DEBUG
+ heap_->relocation_mutex_locked_ = false;
+#endif // DEBUG
heap_->relocation_mutex_->Unlock();
}
}
+#ifdef DEBUG
+ static bool IsLocked(Heap* heap) {
+ return heap->relocation_mutex_locked_;
+ }
+#endif // DEBUG
+
private:
Heap* heap_;
};
@@ -2304,6 +2324,9 @@
MemoryChunk* chunks_queued_for_free_;
Mutex* relocation_mutex_;
+#ifdef DEBUG
+ bool relocation_mutex_locked_;
+#endif // DEBUG;
friend class Factory;
friend class GCTracer;
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 8399f0b..20e41bc 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -348,11 +348,7 @@
}
-HType HType::TypeFromValue(Isolate* isolate, Handle<Object> value) {
- // Handle dereferencing is safe here: an object's type as checked below
- // never changes.
- AllowHandleDereference allow_handle_deref(isolate);
-
+HType HType::TypeFromValue(Handle<Object> value) {
HType result = HType::Tagged();
if (value->IsSmi()) {
result = HType::Smi();
@@ -1309,10 +1305,7 @@
}
if (check_ == IS_INTERNALIZED_STRING && value()->IsConstant()) {
- // Dereferencing is safe here:
- // an internalized string cannot become non-internalized.
- AllowHandleDereference allow_handle_deref(isolate());
- if (HConstant::cast(value())->handle()->IsInternalizedString()) return NULL;
+ if (HConstant::cast(value())->HasInternalizedStringValue()) return NULL;
}
return this;
}
@@ -1814,17 +1807,20 @@
HConstant::HConstant(Handle<Object> handle, Representation r)
- : handle_(handle),
- has_int32_value_(false),
- has_double_value_(false) {
- // Dereferencing here is safe: the value of a number object does not change.
- AllowHandleDereference allow_handle_deref(Isolate::Current());
+ : handle_(handle),
+ has_int32_value_(false),
+ has_double_value_(false),
+ is_internalized_string_(false),
+ boolean_value_(handle->BooleanValue()) {
if (handle_->IsNumber()) {
double n = handle_->Number();
has_int32_value_ = IsInteger32(n);
int32_value_ = DoubleToInt32(n);
double_value_ = n;
has_double_value_ = true;
+ } else {
+ type_from_value_ = HType::TypeFromValue(handle_);
+ is_internalized_string_ = handle_->IsInternalizedString();
}
if (r.IsNone()) {
if (has_int32_value_) {
@@ -1839,18 +1835,44 @@
}
-HConstant::HConstant(int32_t integer_value, Representation r)
+HConstant::HConstant(Handle<Object> handle,
+ Representation r,
+ HType type,
+ bool is_internalize_string,
+ bool boolean_value)
+ : handle_(handle),
+ has_int32_value_(false),
+ has_double_value_(false),
+ is_internalized_string_(is_internalize_string),
+ boolean_value_(boolean_value),
+ type_from_value_(type) {
+ ASSERT(!handle.is_null());
+ ASSERT(!type.IsUninitialized());
+ ASSERT(!type.IsTaggedNumber());
+ Initialize(r);
+}
+
+
+HConstant::HConstant(int32_t integer_value,
+ Representation r,
+ Handle<Object> optional_handle)
: has_int32_value_(true),
has_double_value_(true),
+ is_internalized_string_(false),
+ boolean_value_(integer_value != 0),
int32_value_(integer_value),
double_value_(FastI2D(integer_value)) {
Initialize(r);
}
-HConstant::HConstant(double double_value, Representation r)
+HConstant::HConstant(double double_value,
+ Representation r,
+ Handle<Object> optional_handle)
: has_int32_value_(IsInteger32(double_value)),
has_double_value_(true),
+ is_internalized_string_(false),
+ boolean_value_(double_value != 0 && !isnan(double_value)),
int32_value_(DoubleToInt32(double_value)),
double_value_(double_value) {
Initialize(r);
@@ -1869,53 +1891,27 @@
HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
if (r.IsInteger32() && !has_int32_value_) return NULL;
if (r.IsDouble() && !has_double_value_) return NULL;
- if (handle_.is_null()) {
- ASSERT(has_int32_value_ || has_double_value_);
- if (has_int32_value_) return new(zone) HConstant(int32_value_, r);
- return new(zone) HConstant(double_value_, r);
- }
- return new(zone) HConstant(handle_, r);
+ if (has_int32_value_) return new(zone) HConstant(int32_value_, r, handle_);
+ if (has_double_value_) return new(zone) HConstant(double_value_, r, handle_);
+ ASSERT(!handle_.is_null());
+ return new(zone) HConstant(
+ handle_, r, type_from_value_, is_internalized_string_, boolean_value_);
}
HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const {
if (has_int32_value_) {
- if (handle_.is_null()) {
- return new(zone) HConstant(int32_value_, Representation::Integer32());
- } else {
- // Re-use the existing Handle if possible.
- return new(zone) HConstant(handle_, Representation::Integer32());
- }
- } else if (has_double_value_) {
- return new(zone) HConstant(DoubleToInt32(double_value_),
- Representation::Integer32());
- } else {
- return NULL;
+ return new(zone) HConstant(
+ int32_value_, Representation::Integer32(), handle_);
}
+ if (has_double_value_) {
+ return new(zone) HConstant(
+ DoubleToInt32(double_value_), Representation::Integer32(), handle_);
+ }
+ return NULL;
}
-bool HConstant::ToBoolean() {
- // Converts the constant's boolean value according to
- // ECMAScript section 9.2 ToBoolean conversion.
- if (HasInteger32Value()) return Integer32Value() != 0;
- if (HasDoubleValue()) {
- double v = DoubleValue();
- return v != 0 && !isnan(v);
- }
- // Dereferencing is safe: singletons do not change and strings are
- // immutable.
- AllowHandleDereference allow_handle_deref(isolate());
- if (handle_->IsTrue()) return true;
- if (handle_->IsFalse()) return false;
- if (handle_->IsUndefined()) return false;
- if (handle_->IsNull()) return false;
- if (handle_->IsString() && String::cast(*handle_)->length() == 0) {
- return false;
- }
- return true;
-}
-
void HConstant::PrintDataTo(StringStream* stream) {
if (has_int32_value_) {
stream->Add("%d ", int32_value_);
@@ -2514,6 +2510,12 @@
}
+void HInnerAllocatedObject::PrintDataTo(StringStream* stream) {
+ base_object()->PrintNameTo(stream);
+ stream->Add(" offset %d", offset());
+}
+
+
void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
stream->Add("[%p] = ", *cell());
value()->PrintNameTo(stream);
@@ -2594,7 +2596,8 @@
return Smi::IsValid(int32_value_) ? HType::Smi() : HType::HeapNumber();
}
if (has_double_value_) return HType::HeapNumber();
- return HType::TypeFromValue(isolate(), handle_);
+ ASSERT(!type_from_value_.IsUninitialized());
+ return type_from_value_;
}
@@ -2666,6 +2669,7 @@
void HAllocate::PrintDataTo(StringStream* stream) {
size()->PrintNameTo(stream);
+ if (!GuaranteedInNewSpace()) stream->Add(" (pretenure)");
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index b60a23b..29e8c29 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -122,6 +122,7 @@
V(HasInstanceTypeAndBranch) \
V(InductionVariableAnnotation) \
V(In) \
+ V(InnerAllocatedObject) \
V(InstanceOf) \
V(InstanceOfKnownGlobal) \
V(InstanceSize) \
@@ -385,7 +386,7 @@
return HType(static_cast<Type>(type_ & other.type_));
}
- bool Equals(const HType& other) {
+ bool Equals(const HType& other) const {
return type_ == other.type_;
}
@@ -393,66 +394,66 @@
return Combine(other).Equals(other);
}
- bool IsTagged() {
+ bool IsTagged() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kTagged) == kTagged);
}
- bool IsTaggedPrimitive() {
+ bool IsTaggedPrimitive() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kTaggedPrimitive) == kTaggedPrimitive);
}
- bool IsTaggedNumber() {
+ bool IsTaggedNumber() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kTaggedNumber) == kTaggedNumber);
}
- bool IsSmi() {
+ bool IsSmi() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kSmi) == kSmi);
}
- bool IsHeapNumber() {
+ bool IsHeapNumber() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kHeapNumber) == kHeapNumber);
}
- bool IsString() {
+ bool IsString() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kString) == kString);
}
- bool IsBoolean() {
+ bool IsBoolean() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kBoolean) == kBoolean);
}
- bool IsNonPrimitive() {
+ bool IsNonPrimitive() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kNonPrimitive) == kNonPrimitive);
}
- bool IsJSArray() {
+ bool IsJSArray() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kJSArray) == kJSArray);
}
- bool IsJSObject() {
+ bool IsJSObject() const {
ASSERT(type_ != kUninitialized);
return ((type_ & kJSObject) == kJSObject);
}
- bool IsUninitialized() {
+ bool IsUninitialized() const {
return type_ == kUninitialized;
}
- bool IsHeapObject() {
+ bool IsHeapObject() const {
ASSERT(type_ != kUninitialized);
return IsHeapNumber() || IsString() || IsNonPrimitive();
}
- static HType TypeFromValue(Isolate* isolate, Handle<Object> value);
+ static HType TypeFromValue(Handle<Object> value);
const char* ToString();
@@ -2791,7 +2792,10 @@
virtual intptr_t Hashcode() {
ASSERT_ALLOCATION_DISABLED;
// Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
+ HandleDereferenceGuard allow_handle_deref(isolate(),
+ HandleDereferenceGuard::ALLOW);
+ SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
+ !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
intptr_t hash = 0;
for (int i = 0; i < prototypes_.length(); i++) {
hash = 17 * hash + reinterpret_cast<intptr_t>(*prototypes_[i]);
@@ -3069,8 +3073,17 @@
class HConstant: public HTemplateInstruction<0> {
public:
HConstant(Handle<Object> handle, Representation r);
- HConstant(int32_t value, Representation r);
- HConstant(double value, Representation r);
+ HConstant(int32_t value,
+ Representation r,
+ Handle<Object> optional_handle = Handle<Object>::null());
+ HConstant(double value,
+ Representation r,
+ Handle<Object> optional_handle = Handle<Object>::null());
+ HConstant(Handle<Object> handle,
+ Representation r,
+ HType type,
+ bool is_internalized_string,
+ bool boolean_value);
Handle<Object> handle() {
if (handle_.is_null()) {
@@ -3098,8 +3111,9 @@
Heap* heap = isolate()->heap();
// We should have handled minus_zero_value and nan_value in the
// has_double_value_ clause above.
- // Dereferencing is safe to compare against singletons.
- AllowHandleDereference allow_handle_deref(isolate());
+ // Dereferencing is safe to compare against immovable singletons.
+ HandleDereferenceGuard allow_handle_deref(isolate(),
+ HandleDereferenceGuard::ALLOW);
ASSERT(*handle_ != heap->minus_zero_value());
ASSERT(*handle_ != heap->nan_value());
return *handle_ == heap->undefined_value() ||
@@ -3148,14 +3162,17 @@
bool HasStringValue() const {
if (has_double_value_ || has_int32_value_) return false;
ASSERT(!handle_.is_null());
- return handle_->IsString();
+ return type_from_value_.IsString();
}
Handle<String> StringValue() const {
ASSERT(HasStringValue());
return Handle<String>::cast(handle_);
}
+ bool HasInternalizedStringValue() const {
+ return HasStringValue() && is_internalized_string_;
+ }
- bool ToBoolean();
+ bool BooleanValue() const { return boolean_value_; }
bool IsUint32() {
return HasInteger32Value() && (Integer32Value() >= 0);
@@ -3172,7 +3189,10 @@
} else {
ASSERT(!handle_.is_null());
// Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
+ HandleDereferenceGuard allow_handle_deref(isolate(),
+ HandleDereferenceGuard::ALLOW);
+ SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
+ !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
hash = reinterpret_cast<intptr_t>(*handle_);
}
@@ -3222,8 +3242,11 @@
// not the converse.
bool has_int32_value_ : 1;
bool has_double_value_ : 1;
+ bool is_internalized_string_ : 1; // TODO(yangguo): make this part of HType.
+ bool boolean_value_ : 1;
int32_t int32_value_;
double double_value_;
+ HType type_from_value_;
};
@@ -4525,7 +4548,10 @@
virtual intptr_t Hashcode() {
ASSERT_ALLOCATION_DISABLED;
// Dereferencing to use the object's raw address for hashing is safe.
- AllowHandleDereference allow_handle_deref(isolate());
+ HandleDereferenceGuard allow_handle_deref(isolate(),
+ HandleDereferenceGuard::ALLOW);
+ SLOW_ASSERT(Heap::RelocationLock::IsLocked(isolate()->heap()) ||
+ !isolate()->optimizing_compiler_thread()->IsOptimizerThread());
return reinterpret_cast<intptr_t>(*cell_);
}
@@ -4629,7 +4655,6 @@
: type_(type),
flags_(flags) {
ASSERT((flags & CAN_ALLOCATE_IN_OLD_DATA_SPACE) == 0); // unimplemented
- ASSERT((flags & CAN_ALLOCATE_IN_OLD_POINTER_SPACE) == 0); // unimplemented
SetOperandAt(0, context);
SetOperandAt(1, size);
set_representation(Representation::Tagged());
@@ -4684,6 +4709,31 @@
};
+class HInnerAllocatedObject: public HTemplateInstruction<1> {
+ public:
+ HInnerAllocatedObject(HValue* value, int offset)
+ : offset_(offset) {
+ ASSERT(value->IsAllocate());
+ SetOperandAt(0, value);
+ set_representation(Representation::Tagged());
+ }
+
+ HValue* base_object() { return OperandAt(0); }
+ int offset() { return offset_; }
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::Tagged();
+ }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject)
+
+ private:
+ int offset_;
+};
+
+
inline bool StoringValueNeedsWriteBarrier(HValue* value) {
return !value->type().IsBoolean()
&& !value->type().IsSmi()
@@ -4693,6 +4743,11 @@
inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
HValue* new_space_dominator) {
+ if (object->IsInnerAllocatedObject()) {
+ return ReceiverObjectNeedsWriteBarrier(
+ HInnerAllocatedObject::cast(object)->base_object(),
+ new_space_dominator);
+ }
if (object != new_space_dominator) return true;
if (object->IsFastLiteral()) return false;
if (object->IsAllocateObject()) return false;
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 8499b99..9f63c17 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -505,7 +505,9 @@
void HGraph::Verify(bool do_full_verify) const {
// Allow dereferencing for debug mode verification.
- AllowHandleDereference allow_handle_deref(isolate());
+ Heap::RelocationLock(isolate()->heap());
+ HandleDereferenceGuard allow_handle_deref(isolate(),
+ HandleDereferenceGuard::ALLOW);
for (int i = 0; i < blocks_.length(); i++) {
HBasicBlock* block = blocks_.at(i);
@@ -585,18 +587,6 @@
#endif
-HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
- Handle<Object> value) {
- if (!pointer->is_set()) {
- HConstant* constant = new(zone()) HConstant(value,
- Representation::Tagged());
- constant->InsertAfter(GetConstantUndefined());
- pointer->set(constant);
- }
- return pointer->get();
-}
-
-
HConstant* HGraph::GetConstantInt32(SetOncePointer<HConstant>* pointer,
int32_t value) {
if (!pointer->is_set()) {
@@ -624,19 +614,27 @@
}
-HConstant* HGraph::GetConstantTrue() {
- return GetConstant(&constant_true_, isolate()->factory()->true_value());
+#define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \
+HConstant* HGraph::GetConstant##Name() { \
+ if (!constant_##name##_.is_set()) { \
+ HConstant* constant = new(zone()) HConstant( \
+ isolate()->factory()->name##_value(), \
+ Representation::Tagged(), \
+ htype, \
+ false, \
+ boolean_value); \
+ constant->InsertAfter(GetConstantUndefined()); \
+ constant_##name##_.set(constant); \
+ } \
+ return constant_##name##_.get(); \
}
-HConstant* HGraph::GetConstantFalse() {
- return GetConstant(&constant_false_, isolate()->factory()->false_value());
-}
+DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true)
+DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false)
+DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
-
-HConstant* HGraph::GetConstantHole() {
- return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value());
-}
+#undef DEFINE_GET_CONSTANT
HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id)
@@ -1075,6 +1073,11 @@
total_size->ClearFlag(HValue::kCanOverflow);
HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
+ // TODO(hpayer): add support for old data space
+ if (FLAG_pretenure_literals && !IsFastDoubleElementsKind(kind)) {
+ flags = static_cast<HAllocate::Flags>(
+ flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
+ }
if (IsFastDoubleElementsKind(kind)) {
flags = static_cast<HAllocate::Flags>(
flags | HAllocate::ALLOCATE_DOUBLE_ALIGNED);
@@ -3711,7 +3714,7 @@
}
if (value->IsConstant()) {
HConstant* constant_value = HConstant::cast(value);
- if (constant_value->ToBoolean()) {
+ if (constant_value->BooleanValue()) {
builder->current_block()->Goto(if_true(), builder->function_state());
} else {
builder->current_block()->Goto(if_false(), builder->function_state());
@@ -3878,6 +3881,8 @@
void HGraph::GlobalValueNumbering() {
// Perform common subexpression elimination and loop-invariant code motion.
if (FLAG_use_gvn) {
+ // We use objects' raw addresses for identification, so they must not move.
+ Heap::RelocationLock relocation_lock(isolate()->heap());
HPhase phase("H_Global value numbering", this);
HGlobalValueNumberer gvn(this, info());
bool removed_side_effects = gvn.Analyze();
@@ -9241,8 +9246,8 @@
if (left_value->IsConstant()) {
HConstant* left_constant = HConstant::cast(left_value);
- if ((is_logical_and && left_constant->ToBoolean()) ||
- (!is_logical_and && !left_constant->ToBoolean())) {
+ if ((is_logical_and && left_constant->BooleanValue()) ||
+ (!is_logical_and && !left_constant->BooleanValue())) {
Drop(1); // left_value.
CHECK_BAILOUT(VisitForValue(expr->right()));
}
@@ -10578,13 +10583,17 @@
void HTracer::TraceLithium(const char* name, LChunk* chunk) {
- AllowHandleDereference allow_handle_deref(chunk->isolate());
+ ASSERT(!FLAG_parallel_recompilation);
+ HandleDereferenceGuard allow_handle_deref(chunk->isolate(),
+ HandleDereferenceGuard::ALLOW);
Trace(name, chunk->graph(), chunk);
}
void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
- AllowHandleDereference allow_handle_deref(graph->isolate());
+ ASSERT(!FLAG_parallel_recompilation);
+ HandleDereferenceGuard allow_handle_deref(graph->isolate(),
+ HandleDereferenceGuard::ALLOW);
Trace(name, graph, NULL);
}
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 47fd69d..a35d9a6 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -386,8 +386,6 @@
}
private:
- HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
- Handle<Object> value);
HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
int32_t integer_value);
@@ -422,7 +420,7 @@
SetOncePointer<HConstant> constant_minus1_;
SetOncePointer<HConstant> constant_true_;
SetOncePointer<HConstant> constant_false_;
- SetOncePointer<HConstant> constant_hole_;
+ SetOncePointer<HConstant> constant_the_hole_;
SetOncePointer<HArgumentsObject> arguments_object_;
SetOncePointer<HBasicBlock> osr_loop_entry_;
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 51e16fd..afb1c03 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -1033,12 +1033,7 @@
if (initial_capacity > 0) {
size += FixedArray::SizeFor(initial_capacity);
}
- __ AllocateInNewSpace(size,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT);
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
@@ -1618,12 +1613,12 @@
// Allocate a JSValue and put the tagged pointer into eax.
Label gc_required;
- __ AllocateInNewSpace(JSValue::kSize,
- eax, // Result.
- ecx, // New allocation top (we ignore it).
- no_reg,
- &gc_required,
- TAG_OBJECT);
+ __ Allocate(JSValue::kSize,
+ eax, // Result.
+ ecx, // New allocation top (we ignore it).
+ no_reg,
+ &gc_required,
+ TAG_OBJECT);
// Set the map.
__ LoadGlobalFunctionInitialMap(edi, ecx);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 1b27540..88207c4 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -145,7 +145,7 @@
Counters* counters = masm->isolate()->counters();
Label gc;
- __ AllocateInNewSpace(JSFunction::kSize, eax, ebx, ecx, &gc, TAG_OBJECT);
+ __ Allocate(JSFunction::kSize, eax, ebx, ecx, &gc, TAG_OBJECT);
__ IncrementCounter(counters->fast_new_closure_total(), 1);
@@ -273,8 +273,8 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
- eax, ebx, ecx, &gc, TAG_OBJECT);
+ __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
+ eax, ebx, ecx, &gc, TAG_OBJECT);
// Get the function from the stack.
__ mov(ecx, Operand(esp, 1 * kPointerSize));
@@ -321,8 +321,7 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- eax, ebx, ecx, &gc, TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length), eax, ebx, ecx, &gc, TAG_OBJECT);
// Get the function or sentinel from the stack.
__ mov(ecx, Operand(esp, 1 * kPointerSize));
@@ -414,7 +413,7 @@
if (mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS) {
flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT | flags);
}
- __ AllocateInNewSpace(size, eax, ebx, edx, fail, flags);
+ __ Allocate(size, eax, ebx, edx, fail, flags);
if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
__ mov(FieldOperand(eax, allocation_info_start),
@@ -3301,7 +3300,7 @@
StubCompiler::GenerateLoadArrayLength(masm, edx, eax, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -3320,7 +3319,7 @@
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -3340,7 +3339,7 @@
StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
support_wrapper_);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -3404,7 +3403,7 @@
__ bind(&miss);
- StubCompiler::GenerateStoreMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -6739,12 +6738,8 @@
// Compare lengths - strings up to min-length are equal.
__ bind(&compare_lengths);
__ test(length_delta, length_delta);
-#ifndef ENABLE_LATIN_1
- __ j(not_zero, &result_not_equal, Label::kNear);
-#else
Label length_not_equal;
__ j(not_zero, &length_not_equal, Label::kNear);
-#endif
// Result is EQUAL.
STATIC_ASSERT(EQUAL == 0);
@@ -6753,19 +6748,13 @@
__ ret(0);
Label result_greater;
-#ifdef ENABLE_LATIN_1
Label result_less;
__ bind(&length_not_equal);
__ j(greater, &result_greater, Label::kNear);
__ jmp(&result_less, Label::kNear);
-#endif
__ bind(&result_not_equal);
-#ifndef ENABLE_LATIN_1
- __ j(greater, &result_greater, Label::kNear);
-#else
__ j(above, &result_greater, Label::kNear);
__ bind(&result_less);
-#endif
// Result is LESS.
__ Set(eax, Immediate(Smi::FromInt(LESS)));
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 25c5e65..ebc3a2b 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1489,7 +1489,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 4ae6603..0cd5f1f 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4195,6 +4195,13 @@
}
+void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
+ Register result = ToRegister(instr->result());
+ Register base = ToRegister(instr->base_object());
+ __ lea(result, Operand(base, instr->offset()));
+}
+
+
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register object = ToRegister(instr->object());
Register value = ToRegister(instr->value());
@@ -5461,12 +5468,8 @@
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
- __ AllocateInNewSpace(instance_size,
- result,
- no_reg,
- scratch,
- deferred->entry(),
- TAG_OBJECT);
+ __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
+ TAG_OBJECT);
__ bind(deferred->exit());
if (FLAG_debug_code) {
@@ -5556,7 +5559,10 @@
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
+ if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+ flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+ }
+ __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
@@ -5795,7 +5801,7 @@
// Allocate all objects that are part of the literal in one big
// allocation. This avoids multiple limit checks.
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
@@ -5885,7 +5891,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 69a0e7f..4a380ef 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -292,6 +292,13 @@
}
+void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ base_object()->PrintTo(stream);
+ stream->Add(" + %d", offset());
+}
+
+
void LCallConstantFunction::PrintDataTo(StringStream* stream) {
stream->Add("#%d / ", arity());
}
@@ -718,10 +725,12 @@
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
- operand->set_virtual_register(allocator_->GetVirtualRegister());
+ int vreg = allocator_->GetVirtualRegister();
if (!allocator_->AllocationOk()) {
- Abort("Not enough virtual registers (temps).");
+ Abort("Out of virtual registers while trying to allocate temp register.");
+ return NULL;
}
+ operand->set_virtual_register(vreg);
return operand;
}
@@ -984,7 +993,7 @@
if (value->EmitAtUses()) {
ASSERT(value->IsConstant());
ASSERT(!value->representation().IsDouble());
- HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
+ HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
return new(zone()) LGoto(successor->block_id());
@@ -1081,6 +1090,15 @@
}
+LInstruction* LChunkBuilder::DoInnerAllocatedObject(
+ HInnerAllocatedObject* inner_object) {
+ LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
+ LInnerAllocatedObject* result =
+ new(zone()) LInnerAllocatedObject(base_object);
+ return DefineAsRegister(result);
+}
+
+
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
return instr->HasNoUses()
? NULL
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 318a51f..0e36474 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -184,7 +184,8 @@
V(LoadFieldByIndex) \
V(DateField) \
V(WrapReceiver) \
- V(Drop)
+ V(Drop) \
+ V(InnerAllocatedObject)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
@@ -1681,6 +1682,22 @@
};
+class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LInnerAllocatedObject(LOperand* base_object) {
+ inputs_[0] = base_object;
+ }
+
+ LOperand* base_object() { return inputs_[0]; }
+ int offset() { return hydrogen()->offset(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object")
+ DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject)
+};
+
+
class LThisFunction: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 494a1bf..debf64a 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -618,6 +618,7 @@
void MacroAssembler::DispatchMap(Register obj,
+ Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type) {
@@ -1214,8 +1215,8 @@
void MacroAssembler::LoadAllocationTopHelper(Register result,
Register scratch,
AllocationFlags flags) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
// Just return if allocation top is already known.
if ((flags & RESULT_CONTAINS_TOP) != 0) {
@@ -1223,7 +1224,7 @@
ASSERT(scratch.is(no_reg));
#ifdef DEBUG
// Assert that result actually contains top on entry.
- cmp(result, Operand::StaticVariable(new_space_allocation_top));
+ cmp(result, Operand::StaticVariable(allocation_top));
Check(equal, "Unexpected allocation top");
#endif
return;
@@ -1231,39 +1232,40 @@
// Move address of new object to result. Use scratch register if available.
if (scratch.is(no_reg)) {
- mov(result, Operand::StaticVariable(new_space_allocation_top));
+ mov(result, Operand::StaticVariable(allocation_top));
} else {
- mov(scratch, Immediate(new_space_allocation_top));
+ mov(scratch, Immediate(allocation_top));
mov(result, Operand(scratch, 0));
}
}
void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
- Register scratch) {
+ Register scratch,
+ AllocationFlags flags) {
if (emit_debug_code()) {
test(result_end, Immediate(kObjectAlignmentMask));
Check(zero, "Unaligned allocation in new space");
}
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
// Update new top. Use scratch if available.
if (scratch.is(no_reg)) {
- mov(Operand::StaticVariable(new_space_allocation_top), result_end);
+ mov(Operand::StaticVariable(allocation_top), result_end);
} else {
mov(Operand(scratch, 0), result_end);
}
}
-void MacroAssembler::AllocateInNewSpace(int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
@@ -1287,6 +1289,7 @@
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
if ((flags & DOUBLE_ALIGNMENT) != 0) {
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
Label aligned;
test(result, Immediate(kDoubleAlignmentMask));
@@ -1299,20 +1302,20 @@
Register top_reg = result_end.is_valid() ? result_end : result;
- // Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ // Calculate new top and bail out if space is exhausted.
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
if (!top_reg.is(result)) {
mov(top_reg, result);
}
add(top_reg, Immediate(object_size));
j(carry, gc_required);
- cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
+ cmp(top_reg, Operand::StaticVariable(allocation_limit));
j(above, gc_required);
// Update allocation top.
- UpdateAllocationTopHelper(top_reg, scratch);
+ UpdateAllocationTopHelper(top_reg, scratch, flags);
// Tag result if requested.
bool tag_result = (flags & TAG_OBJECT) != 0;
@@ -1340,6 +1343,7 @@
Label* gc_required,
AllocationFlags flags) {
ASSERT((flags & SIZE_IN_WORDS) == 0);
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1399,7 +1403,7 @@
}
// Update allocation top.
- UpdateAllocationTopHelper(result_end, scratch);
+ UpdateAllocationTopHelper(result_end, scratch, flags);
}
@@ -1410,6 +1414,7 @@
Label* gc_required,
AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -1459,7 +1464,7 @@
}
// Update allocation top.
- UpdateAllocationTopHelper(result_end, scratch);
+ UpdateAllocationTopHelper(result_end, scratch, flags);
}
@@ -1482,12 +1487,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(HeapNumber::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1575,12 +1576,8 @@
ASSERT(length > 0);
// Allocate ASCII string in new space.
- AllocateInNewSpace(SeqOneByteString::SizeFor(length),
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2,
+ gc_required, TAG_OBJECT);
// Set the map, length and hash field.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1597,12 +1594,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1615,12 +1608,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1633,12 +1622,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1651,12 +1636,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
mov(FieldOperand(result, HeapObject::kMapOffset),
@@ -1830,7 +1811,8 @@
void MacroAssembler::TailCallStub(CodeStub* stub) {
- ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+ ASSERT(allow_stub_calls_ ||
+ stub->CompilingCallsToThisStubIsGCSafe(isolate()));
jmp(stub->GetCode(isolate()), RelocInfo::CODE_TARGET);
}
@@ -1843,7 +1825,7 @@
bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
- return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
+ return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(isolate());
}
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 05ad82d..8dd4120 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -410,6 +410,7 @@
// specified target if equal. Skip the smi check if not required (object is
// known to be a heap object)
void DispatchMap(Register obj,
+ Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type);
@@ -564,22 +565,22 @@
// ---------------------------------------------------------------------------
// Allocation support
- // Allocate an object in new space. If the new space is exhausted control
- // continues at the gc_required label. The allocated object is returned in
- // result and end of the new object is returned in result_end. The register
- // scratch can be passed as no_reg in which case an additional object
- // reference will be added to the reloc info. The returned pointers in result
- // and result_end have not yet been tagged as heap objects. If
- // result_contains_top_on_entry is true the content of result is known to be
- // the allocation top on entry (could be result_end from a previous call to
- // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
+ // Allocate an object in new space or old pointer space. If the given space
+ // is exhausted control continues at the gc_required label. The allocated
+ // object is returned in result and end of the new object is returned in
+ // result_end. The register scratch can be passed as no_reg in which case
+ // an additional object reference will be added to the reloc info. The
+ // returned pointers in result and result_end have not yet been tagged as
+ // heap objects. If result_contains_top_on_entry is true the content of
+ // result is known to be the allocation top on entry (could be result_end
+ // from a previous call). If result_contains_top_on_entry is true scratch
// should be no_reg as it is never used.
- void AllocateInNewSpace(int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
void AllocateInNewSpace(int header_size,
ScaleFactor element_size,
@@ -910,7 +911,10 @@
void LoadAllocationTopHelper(Register result,
Register scratch,
AllocationFlags flags);
- void UpdateAllocationTopHelper(Register result_end, Register scratch);
+
+ void UpdateAllocationTopHelper(Register result_end,
+ Register scratch,
+ AllocationFlags flags);
// Helper for PopHandleScope. Allowed to perform a GC and returns
// NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index bb0e0ad..d8f2e8f 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -344,9 +344,6 @@
__ or_(eax, 0x20); // Convert match character to lower-case.
__ lea(ecx, Operand(eax, -'a'));
__ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter?
-#ifndef ENABLE_LATIN_1
- __ j(above, &fail); // Weren't letters anyway.
-#else
Label convert_capture;
__ j(below_equal, &convert_capture); // In range 'a'-'z'.
// Latin-1: Check for values in range [224,254] but not 247.
@@ -356,7 +353,6 @@
__ cmp(ecx, Immediate(247 - 224)); // Check for 247.
__ j(equal, &fail);
__ bind(&convert_capture);
-#endif
// Also convert capture character.
__ movzx_b(ecx, Operand(edx, 0));
__ or_(ecx, 0x20);
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index d0b7881..f7e795e 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -369,19 +369,6 @@
}
-// Load a fast property out of a holder object (src). In-object properties
-// are loaded directly otherwise the property is loaded from the properties
-// fixed array.
-void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst,
- Register src,
- Handle<JSObject> holder,
- PropertyIndex index) {
- DoGenerateFastPropertyLoad(
- masm, dst, src, index.is_inobject(holder), index.translate(holder));
-}
-
-
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst,
Register src,
@@ -729,28 +716,13 @@
};
-void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
- Handle<Code> code = (kind == Code::LOAD_IC)
- ? masm->isolate()->builtins()->LoadIC_Miss()
- : masm->isolate()->builtins()->KeyedLoadIC_Miss();
- __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
- Handle<Code> code = (kind == Code::STORE_IC)
- ? masm->isolate()->builtins()->StoreIC_Miss()
- : masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
- Handle<Code> code =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ jmp(code, RelocInfo::CODE_TARGET);
+void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
+ Label* label,
+ Handle<Name> name) {
+ if (!label->is_unused()) {
+ __ bind(label);
+ __ mov(this->name(), Immediate(name));
+ }
}
@@ -763,9 +735,11 @@
Handle<Name> name,
Register receiver_reg,
Register name_reg,
+ Register value_reg,
Register scratch1,
Register scratch2,
- Label* miss_label) {
+ Label* miss_label,
+ Label* miss_restore_name) {
LookupResult lookup(masm->isolate());
object->Lookup(*name, &lookup);
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
@@ -800,16 +774,8 @@
} while (holder->GetPrototype()->IsJSObject());
}
// We need an extra register, push
- __ push(name_reg);
- Label miss_pop, done_check;
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, &miss_pop);
- __ jmp(&done_check);
- __ bind(&miss_pop);
- __ pop(name_reg);
- __ jmp(miss_label);
- __ bind(&done_check);
- __ pop(name_reg);
+ scratch1, scratch2, name, miss_restore_name);
}
// Stub never generated for non-global objects that require access
@@ -857,11 +823,11 @@
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ mov(FieldOperand(receiver_reg, offset), eax);
+ __ mov(FieldOperand(receiver_reg, offset), value_reg);
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ mov(name_reg, eax);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
offset,
name_reg,
@@ -876,7 +842,7 @@
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ mov(name_reg, eax);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
offset,
name_reg,
@@ -885,6 +851,7 @@
}
// Return the value (register eax).
+ ASSERT(value_reg.is(eax));
__ ret(0);
}
@@ -933,15 +900,16 @@
}
}
-#undef __
-#define __ ACCESS_MASM(masm())
-
-void StubCompiler::GenerateTailCall(Handle<Code> code) {
+void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
__ jmp(code, RelocInfo::CODE_TARGET);
}
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
@@ -1062,7 +1030,7 @@
if (!miss->is_unused()) {
__ jmp(success);
__ bind(miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
}
}
@@ -2581,66 +2549,27 @@
}
-Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Generate store field code. Trashes the name register.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- edx, ecx, ebx, edi,
- &miss);
- // Handle store cache miss.
- __ bind(&miss);
- __ mov(ecx, Immediate(name)); // restore name
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
+ Label miss, miss_restore_name;
// Check that the maps haven't changed, preserving the value register.
- __ push(eax);
- __ JumpIfSmi(edx, &miss);
- CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss);
- __ pop(eax); // restore value
+ __ JumpIfSmi(receiver(), &miss);
+ CheckPrototypes(object, receiver(), holder,
+ scratch1(), this->name(), scratch2(),
+ name, &miss_restore_name);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
- __ pop(ebx); // remove the return address
- __ push(edx); // receiver
- __ push(Immediate(callback)); // callback info
- __ push(ecx); // name
- __ push(eax); // value
- __ push(ebx); // restore return address
+ __ pop(scratch1()); // remove the return address
+ __ push(receiver());
+ __ Push(callback);
+ __ Push(name);
+ __ push(value());
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@@ -2648,13 +2577,12 @@
__ TailCallExternalReference(store_callback_property, 4, 1);
// Handle store cache miss.
+ GenerateRestoreName(masm(), &miss_restore_name, name);
__ bind(&miss);
- __ pop(eax);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::CALLBACKS, name);
+ return GetICCode(kind(), Code::CALLBACKS, name);
}
@@ -2704,67 +2632,30 @@
#define __ ACCESS_MASM(masm())
-Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<Name> name,
- Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<JSFunction> setter) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the maps haven't changed, preserving the name register.
- __ push(ecx);
- __ JumpIfSmi(edx, &miss);
- CheckPrototypes(receiver, edx, holder, ebx, ecx, edi, name, &miss);
- __ pop(ecx);
-
- GenerateStoreViaSetter(masm(), setter);
-
- __ bind(&miss);
- __ pop(ecx);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::CALLBACKS, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
- __ CheckMap(edx, Handle<Map>(receiver->map()),
+ __ CheckMap(receiver(), Handle<Map>(object->map()),
&miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
- if (receiver->IsJSGlobalProxy()) {
+ if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(edx, ebx, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
- ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- __ pop(ebx); // remove the return address
- __ push(edx); // receiver
- __ push(ecx); // name
- __ push(eax); // value
- __ push(Immediate(Smi::FromInt(strict_mode_)));
- __ push(ebx); // restore return address
+ __ pop(scratch1()); // remove the return address
+ __ push(receiver());
+ __ push(this->name());
+ __ push(value());
+ __ push(Immediate(Smi::FromInt(strict_mode())));
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@@ -2773,11 +2664,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::INTERCEPTOR, name);
+ return GetICCode(kind(), Code::INTERCEPTOR, name);
}
@@ -2785,22 +2675,17 @@
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
+ __ cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
Immediate(Handle<Map>(object->map())));
__ j(not_equal, &miss);
// Compute the cell operand to use.
- __ mov(ebx, Immediate(cell));
- Operand cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset);
+ __ mov(scratch1(), Immediate(cell));
+ Operand cell_operand =
+ FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
@@ -2810,7 +2695,7 @@
__ j(equal, &miss);
// Store the value in the cell.
- __ mov(cell_operand, eax);
+ __ mov(cell_operand, value());
// No write barrier here, because cells are always rescanned.
// Return the value (register eax).
@@ -2821,77 +2706,10 @@
// Handle store cache miss.
__ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, name);
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- Counters* counters = isolate()->counters();
- __ IncrementCounter(counters->keyed_store_field(), 1);
-
- // Check that the name has not changed.
- __ cmp(ecx, Immediate(name));
- __ j(not_equal, &miss);
-
- // Generate store field code. Trashes the name register.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- edx, ecx, ebx, edi,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- __ DecrementCounter(counters->keyed_store_field(), 1);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
- Handle<Code> stub =
- KeyedStoreElementStub(is_jsarray,
- elements_kind,
- store_mode_).GetCode(isolate());
-
- __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
-
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string());
+ return GetICCode(kind(), Code::NORMAL, name);
}
@@ -2899,34 +2717,27 @@
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
Label miss;
- __ JumpIfSmi(edx, &miss, Label::kNear);
- __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
- // ebx: receiver->map().
+ __ JumpIfSmi(receiver(), &miss, Label::kNear);
+ __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_maps->length(); ++i) {
- __ cmp(edi, receiver_maps->at(i));
+ __ cmp(scratch1(), receiver_maps->at(i));
if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i));
} else {
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
- __ mov(ebx, Immediate(transitioned_maps->at(i)));
+ __ mov(transition_map(), Immediate(transitioned_maps->at(i)));
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
}
__ bind(&miss);
- Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
+ return GetICCode(
+ kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
}
@@ -2964,6 +2775,20 @@
}
+Register* StoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg };
+ return registers;
+}
+
+
+Register* KeyedStoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg };
+ return registers;
+}
+
+
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
@@ -2972,6 +2797,14 @@
}
+void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss) {
+ __ cmp(name_reg, Immediate(name));
+ __ j(not_equal, miss);
+}
+
+
#undef __
#define __ ACCESS_MASM(masm)
@@ -3050,34 +2883,6 @@
}
-Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
-
- ElementsKind elements_kind = receiver_map->elements_kind();
- if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
- Handle<Code> stub = KeyedLoadFastElementStub(
- receiver_map->instance_type() == JS_ARRAY_TYPE,
- elements_kind).GetCode(isolate());
- __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
- } else {
- Handle<Code> stub =
- KeyedLoadDictionaryElementStub().GetCode(isolate());
- __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
- }
-
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
@@ -3100,7 +2905,7 @@
}
__ bind(&miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
InlineCacheState state =
@@ -3156,8 +2961,8 @@
__ cmp(ecx, Immediate(instance_size));
__ Check(equal, "Instance size of initial map changed.");
#endif
- __ AllocateInNewSpace(instance_size, edx, ecx, no_reg,
- &generic_stub_call, NO_ALLOCATION_FLAGS);
+ __ Allocate(instance_size, edx, ecx, no_reg, &generic_stub_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields and add the heap tag.
// ebx: initial map
@@ -3284,10 +3089,7 @@
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
-
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedLoadIC_Slow();
- __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
__ bind(&miss_force_generic);
// ----------- S t a t e -------------
@@ -3295,10 +3097,7 @@
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
-
- Handle<Code> miss_force_generic_ic =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
}
@@ -3516,9 +3315,7 @@
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
-
- Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
// ----------- S t a t e -------------
// -- eax : value
@@ -3528,9 +3325,7 @@
// -----------------------------------
__ bind(&miss_force_generic);
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
}
@@ -3606,14 +3401,11 @@
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
- Handle<Code> ic_force_generic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
// Handle transition to other elements kinds without using the generic stub.
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Handle transition requiring the array to grow.
@@ -3631,7 +3423,7 @@
__ j(not_equal, &check_capacity);
int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
+ __ Allocate(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
// Restore the key, which is known to be the array length.
// eax: value
@@ -3684,8 +3476,7 @@
__ mov(ecx, Immediate(0));
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
@@ -3734,14 +3525,11 @@
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
- Handle<Code> ic_force_generic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
// Handle transition to other elements kinds without using the generic stub.
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Handle transition requiring the array to grow.
@@ -3767,7 +3555,7 @@
__ j(not_equal, &check_capacity);
int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
+ __ Allocate(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
// Restore the key, which is known to be the array length.
__ mov(ecx, Immediate(0));
@@ -3822,8 +3610,7 @@
__ mov(ecx, Immediate(0));
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
diff --git a/src/isolate.cc b/src/isolate.cc
index 5f7b3f2..fb9cab1 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -944,11 +944,7 @@
if (decision != UNKNOWN) return decision == YES;
// Get named access check callback
- // TODO(dcarney): revert
- Map* map = receiver->map();
- CHECK(map->IsMap());
- CHECK(map->constructor()->IsJSFunction());
- JSFunction* constructor = JSFunction::cast(map->constructor());
+ JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
if (!constructor->shared()->IsApiFunction()) return false;
Object* data_obj =
@@ -1713,7 +1709,8 @@
memset(code_kind_statistics_, 0,
sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
- allow_handle_deref_ = true;
+ allow_compiler_thread_handle_deref_ = true;
+ allow_execution_thread_handle_deref_ = true;
#endif
#ifdef ENABLE_DEBUGGER_SUPPORT
@@ -2321,6 +2318,33 @@
}
+#ifdef DEBUG
+bool Isolate::AllowHandleDereference() {
+ if (allow_execution_thread_handle_deref_ &&
+ allow_compiler_thread_handle_deref_) {
+ // Short-cut to avoid polling thread id.
+ return true;
+ }
+ if (FLAG_parallel_recompilation &&
+ optimizing_compiler_thread()->IsOptimizerThread()) {
+ return allow_compiler_thread_handle_deref_;
+ } else {
+ return allow_execution_thread_handle_deref_;
+ }
+}
+
+
+void Isolate::SetAllowHandleDereference(bool allow) {
+ if (FLAG_parallel_recompilation &&
+ optimizing_compiler_thread()->IsOptimizerThread()) {
+ allow_compiler_thread_handle_deref_ = allow;
+ } else {
+ allow_execution_thread_handle_deref_ = allow;
+ }
+}
+#endif
+
+
HStatistics* Isolate::GetHStatistics() {
if (hstatistics() == NULL) set_hstatistics(new HStatistics());
return hstatistics();
diff --git a/src/isolate.h b/src/isolate.h
index e6f6d16..d6770cc 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -988,8 +988,9 @@
int* code_kind_statistics() { return code_kind_statistics_; }
- bool allow_handle_deref() { return allow_handle_deref_; }
- void set_allow_handle_deref(bool allow) { allow_handle_deref_ = allow; }
+ bool AllowHandleDereference();
+
+ void SetAllowHandleDereference(bool allow);
#endif
#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
@@ -1305,7 +1306,8 @@
JSObject::SpillInformation js_spill_information_;
int code_kind_statistics_[Code::NUMBER_OF_KINDS];
- bool allow_handle_deref_;
+ bool allow_compiler_thread_handle_deref_;
+ bool allow_execution_thread_handle_deref_;
#endif
#ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index e73b1d4..b490521 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -2512,11 +2512,7 @@
// For 2-character preloads in ASCII mode or 1-character preloads in
// TWO_BYTE mode we also use a 16 bit load with zero extend.
if (details->characters() == 2 && compiler->ascii()) {
-#ifndef ENABLE_LATIN_1
- if ((mask & 0x7f7f) == 0xffff) need_mask = false;
-#else
if ((mask & 0xffff) == 0xffff) need_mask = false;
-#endif
} else if (details->characters() == 1 && !compiler->ascii()) {
if ((mask & 0xffff) == 0xffff) need_mask = false;
} else {
@@ -2794,17 +2790,12 @@
// We need to check for the following characters: 0x39c 0x3bc 0x178.
static inline bool RangeContainsLatin1Equivalents(CharacterRange range) {
-#ifdef ENABLE_LATIN_1
// TODO(dcarney): this could be a lot more efficient.
return range.Contains(0x39c) ||
range.Contains(0x3bc) || range.Contains(0x178);
-#else
- return false;
-#endif
}
-#ifdef ENABLE_LATIN_1
static bool RangesContainLatin1Equivalents(ZoneList<CharacterRange>* ranges) {
for (int i = 0; i < ranges->length(); i++) {
// TODO(dcarney): this could be a lot more efficient.
@@ -2812,7 +2803,6 @@
}
return false;
}
-#endif
RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) {
@@ -2826,11 +2816,6 @@
if (elm.type == TextElement::ATOM) {
Vector<const uc16> quarks = elm.data.u_atom->data();
for (int j = 0; j < quarks.length(); j++) {
-#ifndef ENABLE_LATIN_1
- if (quarks[j] > String::kMaxOneByteCharCode) {
- return set_replacement(NULL);
- }
-#else
uint16_t c = quarks[j];
if (c <= String::kMaxOneByteCharCode) continue;
if (!ignore_case) return set_replacement(NULL);
@@ -2842,7 +2827,6 @@
// Convert quark to Latin-1 in place.
uint16_t* copy = const_cast<uint16_t*>(quarks.start());
copy[j] = converted;
-#endif
}
} else {
ASSERT(elm.type == TextElement::CHAR_CLASS);
@@ -2857,19 +2841,15 @@
if (range_count != 0 &&
ranges->at(0).from() == 0 &&
ranges->at(0).to() >= String::kMaxOneByteCharCode) {
-#ifdef ENABLE_LATIN_1
// This will be handled in a later filter.
if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
-#endif
return set_replacement(NULL);
}
} else {
if (range_count == 0 ||
ranges->at(0).from() > String::kMaxOneByteCharCode) {
-#ifdef ENABLE_LATIN_1
// This will be handled in a later filter.
if (ignore_case && RangesContainLatin1Equivalents(ranges)) continue;
-#endif
return set_replacement(NULL);
}
}
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index e3b9a88..6ee9ef2 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -839,8 +839,9 @@
ASSERT(!cur_input->IsUsedAtStart());
LUnallocated* input_copy = cur_input->CopyUnconstrained(zone());
- cur_input->set_virtual_register(GetVirtualRegister());
+ int vreg = GetVirtualRegister();
if (!AllocationOk()) return;
+ cur_input->set_virtual_register(vreg);
if (RequiredRegisterKind(input_copy->virtual_register()) ==
DOUBLE_REGISTERS) {
@@ -1924,6 +1925,7 @@
LiveRange* tail = SplitBetween(current,
current->Start(),
block_pos[reg].InstructionStart());
+ if (!AllocationOk()) return;
AddToUnhandledSorted(tail);
}
@@ -1954,6 +1956,7 @@
} else {
SpillBetween(range, split_pos, next_pos->pos());
}
+ if (!AllocationOk()) return;
ActiveToHandled(range);
--i;
}
@@ -1972,6 +1975,7 @@
next_intersection = Min(next_intersection, next_pos->pos());
SpillBetween(range, split_pos, next_intersection);
}
+ if (!AllocationOk()) return;
InactiveToHandled(range);
--i;
}
@@ -1997,8 +2001,9 @@
ASSERT(pos.IsInstructionStart() ||
!chunk_->instructions()->at(pos.InstructionIndex())->IsControl());
- LiveRange* result = LiveRangeFor(GetVirtualRegister());
+ int vreg = GetVirtualRegister();
if (!AllocationOk()) return NULL;
+ LiveRange* result = LiveRangeFor(vreg);
range->SplitAt(pos, result, zone_);
return result;
}
@@ -2075,6 +2080,7 @@
second_part,
second_part->Start().InstructionEnd(),
end.PrevInstruction().InstructionEnd());
+ if (!AllocationOk()) return;
ASSERT(third_part != second_part);
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index 2ca8537..0e24d54 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -427,8 +427,10 @@
Zone* zone() const { return zone_; }
int GetVirtualRegister() {
- if (next_virtual_register_ > LUnallocated::kMaxVirtualRegisters) {
+ if (next_virtual_register_ >= LUnallocated::kMaxVirtualRegisters) {
allocation_ok_ = false;
+ // Maintain the invariant that we return something below the maximum.
+ return 0;
}
return next_virtual_register_++;
}
diff --git a/src/log.h b/src/log.h
index 27d517a..5c121bc 100644
--- a/src/log.h
+++ b/src/log.h
@@ -139,6 +139,7 @@
V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \
V(STORE_IC_TAG, "StoreIC") \
+ V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \
V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \
V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \
diff --git a/src/macro-assembler.h b/src/macro-assembler.h
index 9e71123..55dccfa 100644
--- a/src/macro-assembler.h
+++ b/src/macro-assembler.h
@@ -49,7 +49,9 @@
// words instead of bytes.
SIZE_IN_WORDS = 1 << 2,
// Align the allocation to a multiple of kDoubleSize
- DOUBLE_ALIGNMENT = 1 << 3
+ DOUBLE_ALIGNMENT = 1 << 3,
+ // Directly allocate in old pointer space
+ PRETENURE_OLD_POINTER_SPACE = 1 << 4
};
@@ -168,6 +170,26 @@
#endif // DEBUG
+
+class AllocationUtils {
+ public:
+ static ExternalReference GetAllocationTopReference(
+ Isolate* isolate, AllocationFlags flags) {
+ return ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) ?
+ ExternalReference::old_pointer_space_allocation_top_address(isolate) :
+ ExternalReference::new_space_allocation_top_address(isolate);
+ }
+
+
+ static ExternalReference GetAllocationLimitReference(
+ Isolate* isolate, AllocationFlags flags) {
+ return ((flags & PRETENURE_OLD_POINTER_SPACE) != 0) ?
+ ExternalReference::old_pointer_space_allocation_limit_address(isolate) :
+ ExternalReference::new_space_allocation_limit_address(isolate);
+ }
+};
+
+
} } // namespace v8::internal
#endif // V8_MACRO_ASSEMBLER_H_
diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h
index 1dad815..9c9f611 100644
--- a/src/mips/assembler-mips-inl.h
+++ b/src/mips/assembler-mips-inl.h
@@ -139,14 +139,14 @@
Address RelocInfo::target_address() {
- ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
return Assembler::target_address_at(pc_);
}
Address RelocInfo::target_address_address() {
ASSERT(IsCodeTarget(rmode_) ||
- rmode_ == RUNTIME_ENTRY ||
+ IsRuntimeEntry(rmode_) ||
rmode_ == EMBEDDED_OBJECT ||
rmode_ == EXTERNAL_REFERENCE);
// Read the address of the word containing the target_address in an
@@ -174,7 +174,7 @@
void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
- ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
+ ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
Assembler::set_target_address_at(pc_, target);
if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
Object* target_code = Code::GetCodeFromTargetAddress(target);
@@ -372,7 +372,7 @@
Isolate::Current()->debug()->has_break_points()) {
visitor->VisitDebugTarget(this);
#endif
- } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+ } else if (RelocInfo::IsRuntimeEntry(mode)) {
visitor->VisitRuntimeEntry(this);
}
}
@@ -399,7 +399,7 @@
IsPatchedDebugBreakSlotSequence()))) {
StaticVisitor::VisitDebugTarget(heap, this);
#endif
- } else if (mode == RelocInfo::RUNTIME_ENTRY) {
+ } else if (RelocInfo::IsRuntimeEntry(mode)) {
StaticVisitor::VisitRuntimeEntry(this);
}
}
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 1af9d3f..f398a4d 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -4585,7 +4585,7 @@
StubCompiler::GenerateLoadArrayLength(masm, receiver, a3, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4614,7 +4614,7 @@
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4645,7 +4645,7 @@
support_wrapper_);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -4715,7 +4715,7 @@
__ bind(&miss);
- StubCompiler::GenerateStoreMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 3cd89b8..400f26d 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1268,12 +1268,12 @@
__ sll(result, left, shift);
} else if (IsPowerOf2(constant_abs - 1)) {
int32_t shift = WhichPowerOf2(constant_abs - 1);
- __ sll(result, left, shift);
- __ Addu(result, result, left);
+ __ sll(scratch, left, shift);
+ __ Addu(result, scratch, left);
} else if (IsPowerOf2(constant_abs + 1)) {
int32_t shift = WhichPowerOf2(constant_abs + 1);
- __ sll(result, left, shift);
- __ Subu(result, result, left);
+ __ sll(scratch, left, shift);
+ __ Subu(result, scratch, left);
}
// Correct the sign of the result is the constant is negative.
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index b233d51..f04a462 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -668,8 +668,12 @@
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
- operand->set_virtual_register(allocator_->GetVirtualRegister());
- if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
+ int vreg = allocator_->GetVirtualRegister();
+ if (!allocator_->AllocationOk()) {
+ Abort("Out of virtual registers while trying to allocate temp register.");
+ return NULL;
+ }
+ operand->set_virtual_register(vreg);
return operand;
}
@@ -928,7 +932,7 @@
LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
HValue* value = instr->value();
if (value->EmitAtUses()) {
- HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
+ HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
return new(zone()) LGoto(successor->block_id());
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 242fa1e..af436b6 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3960,7 +3960,8 @@
void MacroAssembler::TailCallStub(CodeStub* stub) {
- ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+ ASSERT(allow_stub_calls_ ||
+ stub->CompilingCallsToThisStubIsGCSafe(isolate()));
Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET);
}
@@ -4078,7 +4079,7 @@
bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
- return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
+ return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(isolate());
}
@@ -4914,8 +4915,8 @@
push(object);
lw(object, FieldMemOperand(object, HeapObject::kMapOffset));
lbu(object, FieldMemOperand(object, Map::kInstanceTypeOffset));
- pop(object);
Check(le, "Operand is not a name", object, Operand(LAST_NAME_TYPE));
+ pop(object);
}
}
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index ce2d635..036cbb1 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -341,9 +341,6 @@
__ Or(t0, t0, Operand(0x20)); // Also convert input character.
__ Branch(&fail, ne, t0, Operand(a3));
__ Subu(a3, a3, Operand('a'));
-#ifndef ENABLE_LATIN_1
- __ Branch(&fail, hi, a3, Operand('z' - 'a')); // Is a3 a lowercase letter?
-#else
__ Branch(&loop_check, ls, a3, Operand('z' - 'a'));
// Latin-1: Check for values in range [224,254] but not 247.
__ Subu(a3, a3, Operand(224 - 'a'));
@@ -351,7 +348,6 @@
__ Branch(&fail, hi, a3, Operand(254 - 224));
// Check for 247.
__ Branch(&fail, eq, a3, Operand(247 - 224));
-#endif
__ bind(&loop_check);
__ Branch(&loop, lt, a0, Operand(a1));
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 4d58c75..959da8e 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -307,19 +307,6 @@
}
-// Load a fast property out of a holder object (src). In-object properties
-// are loaded directly otherwise the property is loaded from the properties
-// fixed array.
-void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst,
- Register src,
- Handle<JSObject> holder,
- PropertyIndex index) {
- DoGenerateFastPropertyLoad(
- masm, dst, src, index.is_inobject(holder), index.translate(holder));
-}
-
-
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst,
Register src,
@@ -433,9 +420,11 @@
Handle<Name> name,
Register receiver_reg,
Register name_reg,
+ Register value_reg,
Register scratch1,
Register scratch2,
- Label* miss_label) {
+ Label* miss_label,
+ Label* miss_restore_name) {
// a0 : value.
Label exit;
@@ -472,17 +461,8 @@
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- // We need an extra register, push
- __ push(name_reg);
- Label miss_pop, done_check;
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, &miss_pop);
- __ jmp(&done_check);
- __ bind(&miss_pop);
- __ pop(name_reg);
- __ jmp(miss_label);
- __ bind(&done_check);
- __ pop(name_reg);
+ scratch1, scratch2, name, miss_restore_name);
}
// Stub never generated for non-global objects that require access
@@ -528,14 +508,14 @@
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ sw(a0, FieldMemOperand(receiver_reg, offset));
+ __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
// Skip updating write barrier if storing a smi.
- __ JumpIfSmi(a0, &exit, scratch1);
+ __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address.
// Pass the now unused name_reg as a scratch register.
- __ mov(name_reg, a0);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(receiver_reg,
offset,
name_reg,
@@ -548,14 +528,14 @@
// Get the properties array.
__ lw(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ sw(a0, FieldMemOperand(scratch1, offset));
+ __ sw(value_reg, FieldMemOperand(scratch1, offset));
// Skip updating write barrier if storing a smi.
- __ JumpIfSmi(a0, &exit);
+ __ JumpIfSmi(value_reg, &exit);
// Update the write barrier for the array address.
// Ok to clobber receiver_reg and name_reg, since we return.
- __ mov(name_reg, a0);
+ __ mov(name_reg, value_reg);
__ RecordWriteField(scratch1,
offset,
name_reg,
@@ -565,27 +545,20 @@
}
// Return the value (register v0).
+ ASSERT(value_reg.is(a0));
__ bind(&exit);
__ mov(v0, a0);
__ Ret();
}
-void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
- Handle<Code> code = (kind == Code::LOAD_IC)
- ? masm->isolate()->builtins()->LoadIC_Miss()
- : masm->isolate()->builtins()->KeyedLoadIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
- Handle<Code> code = (kind == Code::STORE_IC)
- ? masm->isolate()->builtins()->StoreIC_Miss()
- : masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
+void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
+ Label* label,
+ Handle<Name> name) {
+ if (!label->is_unused()) {
+ __ bind(label);
+ __ li(this->name(), Operand(name));
+ }
}
@@ -1064,15 +1037,15 @@
}
-#undef __
-#define __ ACCESS_MASM(masm())
-
-
-void StubCompiler::GenerateTailCall(Handle<Code> code) {
+void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
__ Jump(code, RelocInfo::CODE_TARGET);
}
+#undef __
+#define __ ACCESS_MASM(masm())
+
+
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
@@ -1190,7 +1163,7 @@
if (!miss->is_unused()) {
__ Branch(success);
__ bind(miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
}
}
@@ -2629,38 +2602,6 @@
}
-Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : receiver
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
- Label miss;
-
- // Name register might be clobbered.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- a1, a2, a3, t0,
- &miss);
- __ bind(&miss);
- __ li(a2, Operand(Handle<Name>(name))); // Restore name.
- Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
Handle<JSObject> receiver,
@@ -2693,11 +2634,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::CALLBACKS, name);
+ return GetICCode(kind(), Code::CALLBACKS, name);
}
@@ -2767,11 +2707,10 @@
GenerateStoreViaSetter(masm(), setter);
__ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::CALLBACKS, name);
+ return GetICCode(kind(), Code::CALLBACKS, name);
}
@@ -2801,7 +2740,7 @@
__ Push(a1, a2, a0); // Receiver, name, value.
- __ li(a0, Operand(Smi::FromInt(strict_mode_)));
+ __ li(a0, Operand(Smi::FromInt(strict_mode())));
__ push(a0); // Strict mode.
// Do tail-call to the runtime system.
@@ -2812,11 +2751,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::INTERCEPTOR, name);
+ return GetICCode(kind(), Code::INTERCEPTOR, name);
}
@@ -2857,11 +2795,10 @@
// Handle store cache miss.
__ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3);
- Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, name);
+ return GetICCode(kind(), Code::NORMAL, name);
}
@@ -2898,6 +2835,20 @@
}
+Register* StoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { a1, a2, a0, a3, t0, t1 };
+ return registers;
+}
+
+
+Register* KeyedStoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { a2, a1, a0, a3, t0, t1 };
+ return registers;
+}
+
+
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
@@ -2905,6 +2856,13 @@
}
+void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss) {
+ __ Branch(miss, ne, name_reg, Operand(name));
+}
+
+
#undef __
#define __ ACCESS_MASM(masm)
@@ -2998,8 +2956,7 @@
__ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK);
}
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
@@ -3029,7 +2986,7 @@
}
__ bind(&miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
InlineCacheState state =
@@ -3038,47 +2995,6 @@
}
-Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : key
- // -- a2 : receiver
- // -- ra : return address
- // -----------------------------------
-
- Label miss;
-
- Counters* counters = masm()->isolate()->counters();
- __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0);
-
- // Check that the name has not changed.
- __ Branch(&miss, ne, a1, Operand(name));
-
- // a3 is used as scratch register. a1 and a2 keep their values if a jump to
- // the miss label is generated.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- a2, a1, a3, t0,
- &miss);
- __ bind(&miss);
-
- __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0);
- Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
Handle<Map> receiver_map) {
// ----------- S t a t e -------------
@@ -3097,11 +3013,10 @@
__ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string());
+ return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
}
@@ -3135,11 +3050,11 @@
}
__ bind(&miss);
- Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
+ return GetICCode(
+ kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
}
@@ -3327,9 +3242,7 @@
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedLoadIC_Slow();
- __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
// Miss case, call the runtime.
__ bind(&miss_force_generic);
@@ -3339,10 +3252,7 @@
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
-
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
}
@@ -3796,9 +3706,7 @@
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
// Miss case, call the runtime.
__ bind(&miss_force_generic);
@@ -3808,10 +3716,7 @@
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
-
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
}
@@ -3902,13 +3807,10 @@
__ Ret();
__ bind(&miss_force_generic);
- Handle<Code> ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -3972,8 +3874,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
@@ -4049,13 +3950,10 @@
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
- Handle<Code> ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -4138,8 +4036,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ Jump(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index a3665e9..abfe693 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -318,11 +318,12 @@
"\nException thrown while compiling natives - see above.\n\n");
exit(1);
}
+ Isolate* isolate = context->GetIsolate();
if (i::FLAG_extra_code != NULL) {
context->Enter();
// Capture 100 frames if anything happens.
V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
- HandleScope scope;
+ HandleScope scope(isolate);
const char* name = i::FLAG_extra_code;
FILE* file = i::OS::FOpen(name, "rb");
if (file == NULL) {
@@ -375,7 +376,7 @@
context->Exit();
}
// Make sure all builtin scripts are cached.
- { HandleScope scope;
+ { HandleScope scope(isolate);
for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
i::Isolate::Current()->bootstrapper()->NativesSourceLookup(i);
}
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 3cb3d24..82a71a5 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -486,19 +486,10 @@
ConsString::cast(this)->ConsStringVerify();
} else if (IsSlicedString()) {
SlicedString::cast(this)->SlicedStringVerify();
- } else if (IsSeqOneByteString()) {
- SeqOneByteString::cast(this)->SeqOneByteStringVerify();
}
}
-void SeqOneByteString::SeqOneByteStringVerify() {
-#ifndef ENABLE_LATIN_1
- CHECK(String::IsAscii(GetChars(), length()));
-#endif
-}
-
-
void ConsString::ConsStringVerify() {
CHECK(this->first()->IsString());
CHECK(this->second() == GetHeap()->empty_string() ||
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 7ddfdfc..9a520b2 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -357,12 +357,7 @@
bool String::HasOnlyAsciiChars() {
uint32_t type = map()->instance_type();
-#ifndef ENABLE_LATIN_1
- return (type & kStringEncodingMask) == kOneByteStringTag ||
- (type & kAsciiDataHintMask) == kAsciiDataHintTag;
-#else
return (type & kAsciiDataHintMask) == kAsciiDataHintTag;
-#endif
}
diff --git a/src/objects.cc b/src/objects.cc
index a57e264..3de981c 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -768,8 +768,6 @@
// that even though we may not actually end up loading the named
// property from the current object, we still check that we have
// access to it.
- // TODO(dcarney): revert.
- CHECK(current->IsJSObject());
JSObject* checked = JSObject::cast(current);
if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
return checked->GetPropertyWithFailedAccessCheck(receiver,
@@ -9110,7 +9108,7 @@
} else if (last_comment != NULL &&
bailout_id == Deoptimizer::GetDeoptimizationId(
info->target_address(), Deoptimizer::EAGER)) {
- CHECK(info->rmode() == RelocInfo::RUNTIME_ENTRY);
+ CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
PrintF(" %s\n", last_comment);
return;
}
diff --git a/src/objects.h b/src/objects.h
index 9d52554..89ebf21 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -7796,8 +7796,6 @@
// Q.v. String::kMaxLength which is the maximal size of concatenated strings.
static const int kMaxLength = (kMaxSize - kHeaderSize);
- DECLARE_VERIFIER(SeqOneByteString)
-
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqOneByteString);
};
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index abcce7b..b982b94 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -76,29 +76,20 @@
void OptimizingCompilerThread::CompileNext() {
- Heap::RelocationLock relocation_lock(isolate_->heap());
OptimizingCompiler* optimizing_compiler = NULL;
input_queue_.Dequeue(&optimizing_compiler);
Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
- ASSERT(optimizing_compiler->info()->closure()->IsInRecompileQueue());
-
+ // The function may have already been optimized by OSR. Simply continue.
OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph();
+ USE(status); // Prevent an unused-variable error in release mode.
ASSERT(status != OptimizingCompiler::FAILED);
- // Prevent an unused-variable error in release mode.
- USE(status);
- output_queue_.Enqueue(optimizing_compiler);
-
- // The execution thread can call InstallOptimizedFunctions() at any time,
- // including at this point, after queuing for install and before marking
- // for install. To avoid race condition, functions that are queued but not
- // yet marked for install are not processed by InstallOptimizedFunctions().
-
- ASSERT(optimizing_compiler->info()->closure()->IsInRecompileQueue());
- // Mark function to generate and install optimized code. We assume this
- // write to be atomic.
+ // The function may have already been optimized by OSR. Simply continue.
+ // Mark it for installing before queuing so that we can be sure of the write
+ // order: marking first and (after being queued) installing code second.
optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode();
+ output_queue_.Enqueue(optimizing_compiler);
}
@@ -109,10 +100,6 @@
stop_semaphore_->Wait();
if (FLAG_parallel_recompilation_delay != 0) {
- // Execution ended before we managed to compile and install the remaining
- // functions in the queue. We still want to do that for debugging though.
- // At this point the optimizing thread already stopped, so we finish
- // processing the queue in the main thread.
InstallOptimizedFunctions();
// Barrier when loading queue length is not necessary since the write
// happens in CompileNext on the same thread.
@@ -136,23 +123,9 @@
HandleScope handle_scope(isolate_);
int functions_installed = 0;
while (!output_queue_.IsEmpty()) {
- OptimizingCompiler* compiler = *output_queue_.Peek();
-
- if (compiler->info()->closure()->IsInRecompileQueue()) {
- // A function may be queued for install, but not marked as such yet.
- // We continue with the output queue the next to avoid race condition.
- break;
- }
+ OptimizingCompiler* compiler;
output_queue_.Dequeue(&compiler);
-
-#ifdef DEBUG
- // Create new closure handle since the deferred handle is about to die.
- Handle<JSFunction> closure(*compiler->info()->closure());
-#endif // DEBUG
-
Compiler::InstallOptimizedCode(compiler);
- // Assert that the marker builtin has been replaced by actual code.
- ASSERT(!closure->IsInRecompileQueue());
functions_installed++;
}
}
@@ -163,6 +136,7 @@
ASSERT(IsQueueAvailable());
ASSERT(!IsOptimizerThread());
Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
+ optimizing_compiler->info()->closure()->MarkInRecompileQueue();
input_queue_.Enqueue(optimizing_compiler);
input_queue_semaphore_->Signal();
}
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index 40599ff..8cb5e2d 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -93,7 +93,6 @@
Isolate* isolate_;
Semaphore* stop_semaphore_;
Semaphore* input_queue_semaphore_;
- Semaphore* output_queue_semaphore_;
UnboundQueue<OptimizingCompiler*> input_queue_;
UnboundQueue<OptimizingCompiler*> output_queue_;
volatile AtomicWord stop_thread_;
diff --git a/src/runtime.cc b/src/runtime.cc
index f68672d..12777e7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -5675,9 +5675,7 @@
namespace {
static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
-#ifdef ENABLE_LATIN_1
static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
-#endif
// Given a word and two range boundaries returns a word with high bit
// set in every byte iff the corresponding input byte was strictly in
@@ -5690,11 +5688,6 @@
// Use strict inequalities since in edge cases the function could be
// further simplified.
ASSERT(0 < m && m < n);
-#ifndef ENABLE_LATIN_1
- // Every byte in an ASCII string is less than or equal to 0x7F.
- ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
- ASSERT(n < 0x7F);
-#endif
// Has high bit set in every w byte less than n.
uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
// Has high bit set in every w byte greater than m.
@@ -5711,11 +5704,7 @@
template <AsciiCaseConversion dir>
struct FastAsciiConverter {
-#ifdef ENABLE_LATIN_1
static bool Convert(char* dst, char* src, int length, bool* changed_out) {
-#else
- static bool Convert(char* dst, char* src, int length) {
-#endif
#ifdef DEBUG
char* saved_dst = dst;
char* saved_src = src;
@@ -5727,18 +5716,14 @@
const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
bool changed = false;
-#ifdef ENABLE_LATIN_1
uintptr_t or_acc = 0;
-#endif
char* const limit = src + length;
#ifdef V8_HOST_CAN_READ_UNALIGNED
// Process the prefix of the input that requires no conversion one
// (machine) word at a time.
while (src <= limit - sizeof(uintptr_t)) {
uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
-#ifdef ENABLE_LATIN_1
or_acc |= w;
-#endif
if (AsciiRangeMask(w, lo, hi) != 0) {
changed = true;
break;
@@ -5751,9 +5736,7 @@
// required one word at a time.
while (src <= limit - sizeof(uintptr_t)) {
uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
-#ifdef ENABLE_LATIN_1
or_acc |= w;
-#endif
uintptr_t m = AsciiRangeMask(w, lo, hi);
// The mask has high (7th) bit set in every byte that needs
// conversion and we know that the distance between cases is
@@ -5767,9 +5750,7 @@
// unaligned access is not supported).
while (src < limit) {
char c = *src;
-#ifdef ENABLE_LATIN_1
or_acc |= c;
-#endif
if (lo < c && c < hi) {
c ^= (1 << 5);
changed = true;
@@ -5778,20 +5759,14 @@
++src;
++dst;
}
-#ifdef ENABLE_LATIN_1
if ((or_acc & kAsciiMask) != 0) {
return false;
}
-#endif
#ifdef DEBUG
CheckConvert(saved_dst, saved_src, length, changed);
#endif
-#ifdef ENABLE_LATIN_1
*changed_out = changed;
return true;
-#else
- return changed;
-#endif
}
#ifdef DEBUG
@@ -5856,13 +5831,6 @@
if (!maybe_o->ToObject(&o)) return maybe_o;
}
SeqOneByteString* result = SeqOneByteString::cast(o);
-#ifndef ENABLE_LATIN_1
- bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
- reinterpret_cast<char*>(result->GetChars()),
- reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
- length);
- return has_changed_character ? result : s;
-#else
bool has_changed_character;
bool is_ascii = ConvertTraits::AsciiConverter::Convert(
reinterpret_cast<char*>(result->GetChars()),
@@ -5873,7 +5841,6 @@
if (is_ascii) {
return has_changed_character ? result : s;
}
-#endif
}
Object* answer;
@@ -7762,7 +7729,7 @@
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (!AllowOptimization(isolate, function)) {
function->ReplaceCode(function->shared()->code());
- return function->code();
+ return isolate->heap()->undefined_value();
}
function->shared()->code()->set_profiler_ticks(0);
ASSERT(FLAG_parallel_recompilation);
@@ -7775,10 +7742,13 @@
HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- if (!V8::UseCrankshaft()) return isolate->heap()->undefined_value();
- ASSERT(FLAG_parallel_recompilation);
+ ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation);
OptimizingCompilerThread* opt_thread = isolate->optimizing_compiler_thread();
- opt_thread->InstallOptimizedFunctions();
+ do {
+ // The function could have been marked for installing, but not queued just
+ // yet. In this case, retry until installed.
+ opt_thread->InstallOptimizedFunctions();
+ } while (function->IsMarkedForInstallingRecompiledCode());
return function->code();
}
@@ -9127,6 +9097,27 @@
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldPointerSpace) {
+ // Allocate a block of memory in old pointer space (filled with a filler).
+ // Use as fallback for allocation in generated code when old pointer space
+ // is full.
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
+ int size = size_smi->value();
+ RUNTIME_ASSERT(IsAligned(size, kPointerSize));
+ RUNTIME_ASSERT(size > 0);
+ Heap* heap = isolate->heap();
+ Object* allocation;
+ { MaybeObject* maybe_allocation =
+ heap->old_pointer_space()->AllocateRaw(size);
+ if (maybe_allocation->ToObject(&allocation)) {
+ heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
+ }
+ return maybe_allocation;
+ }
+}
+
+
// Push an object unto an array of objects if it is not already in the
// array. Returns true if the element was pushed on the stack and
// false otherwise.
diff --git a/src/runtime.h b/src/runtime.h
index 934de82..2959fed 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -101,6 +101,7 @@
F(CompileForOnStackReplacement, 1, 1) \
F(SetNewFunctionAttributes, 1, 1) \
F(AllocateInNewSpace, 1, 1) \
+ F(AllocateInOldPointerSpace, 1, 1) \
F(SetNativeFlag, 1, 1) \
F(StoreArrayLiteralElement, 5, 1) \
F(DebugCallbackSupportsStepping, 1, 1) \
diff --git a/src/serialize.cc b/src/serialize.cc
index e587dfa..0ba730f 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -544,6 +544,20 @@
UNCLASSIFIED,
55,
"Runtime::AllocateInNewSpace");
+ Add(ExternalReference::old_pointer_space_allocation_top_address(
+ isolate).address(),
+ UNCLASSIFIED,
+ 56,
+ "Heap::OldPointerSpaceAllocationTopAddress");
+ Add(ExternalReference::old_pointer_space_allocation_limit_address(
+ isolate).address(),
+ UNCLASSIFIED,
+ 57,
+ "Heap::OldPointerSpaceAllocationLimitAddress");
+ Add(ExternalReference(Runtime::kAllocateInOldPointerSpace, isolate).address(),
+ UNCLASSIFIED,
+ 58,
+ "Runtime::AllocateInOldPointerSpace");
// Add a small set of deopt entry addresses to encoder without generating the
// deopt table code, which isn't possible at deserialization time.
@@ -554,7 +568,7 @@
entry,
Deoptimizer::LAZY,
Deoptimizer::CALCULATE_ENTRY_ADDRESS);
- Add(address, LAZY_DEOPTIMIZATION, 56 + entry, "lazy_deopt");
+ Add(address, LAZY_DEOPTIMIZATION, 59 + entry, "lazy_deopt");
}
}
diff --git a/src/spaces.cc b/src/spaces.cc
index 701d46f..2952fd5 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -537,6 +537,17 @@
void MemoryChunk::InsertAfter(MemoryChunk* other) {
next_chunk_ = other->next_chunk_;
prev_chunk_ = other;
+
+ // This memory barrier is needed since concurrent sweeper threads may iterate
+ // over the list of pages while a new page is inserted.
+ // TODO(hpayer): find a cleaner way to guarantee that the page list can be
+ // expanded concurrently
+ MemoryBarrier();
+
+ // The following two write operations can take effect in arbitrary order
+ // since pages are always iterated by the sweeper threads in LIFO order, i.e,
+ // the inserted page becomes visible for the sweeper threads after
+ // other->next_chunk_ = this;
other->next_chunk_->prev_chunk_ = this;
other->next_chunk_ = this;
}
diff --git a/src/spaces.h b/src/spaces.h
index 6847b31..39c19a4 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1663,6 +1663,10 @@
Address top() { return allocation_info_.top; }
Address limit() { return allocation_info_.limit; }
+ // The allocation top and limit addresses.
+ Address* allocation_top_address() { return &allocation_info_.top; }
+ Address* allocation_limit_address() { return &allocation_info_.limit; }
+
// Allocate the requested number of bytes in the space if possible, return a
// failure object if not.
MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
diff --git a/src/string-search.h b/src/string-search.h
index 86237f3..bc685ff 100644
--- a/src/string-search.h
+++ b/src/string-search.h
@@ -53,11 +53,7 @@
// a potentially less efficient searching, but is a safe approximation.
// For needles using only characters in the same Unicode 256-code point page,
// there is no search speed degradation.
-#ifndef ENABLE_LATIN_1
- static const int kAsciiAlphabetSize = 128;
-#else
static const int kAsciiAlphabetSize = 256;
-#endif
static const int kUC16AlphabetSize = Isolate::kUC16AlphabetSize;
// Bad-char shift table stored in the state. It's length is the alphabet size.
@@ -155,11 +151,7 @@
void PopulateBoyerMooreTable();
static inline bool exceedsOneByte(uint8_t c) {
-#ifdef ENABLE_LATIN_1
return false;
-#else
- return c > String::kMaxOneByteCharCodeU;
-#endif
}
static inline bool exceedsOneByte(uint16_t c) {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index ac94fff..3dba2d6 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -112,9 +112,9 @@
Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
- Code::StubType type) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, Code::kNoExtraICState, type);
+ Code::StubType type,
+ Code::ExtraICState extra_ic_state) {
+ Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_ic_state, type);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
@@ -122,18 +122,14 @@
}
-Handle<Code> StubCache::FindStub(Handle<Name> name,
- Handle<JSObject> stub_holder,
- Code::Kind kind,
- Code::StubType type) {
+Handle<Code> StubCache::FindHandler(Handle<Name> name,
+ Handle<JSObject> stub_holder,
+ Code::Kind kind,
+ Code::StubType type,
+ Code::ExtraICState extra_ic_state) {
ASSERT(type != Code::NORMAL);
- int extra_flags = -1;
- if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
- extra_flags = kind;
- kind = Code::STUB;
- }
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, Code::kNoExtraICState, type, extra_flags);
+ Code::STUB, extra_ic_state, type, kind);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
@@ -197,7 +193,7 @@
// Compile the stub that is either shared for all names or
// name specific if there are global objects involved.
- Handle<Code> handler = FindStub(
+ Handle<Code> handler = FindHandler(
cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
if (!handler.is_null()) return handler;
@@ -221,7 +217,7 @@
}
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub;
@@ -240,7 +236,7 @@
Handle<ExecutableAccessorInfo> callback) {
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
@@ -257,7 +253,7 @@
Handle<JSObject> holder,
Handle<JSFunction> getter) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
@@ -274,7 +270,7 @@
Handle<JSObject> holder,
Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> handler = FindStub(
+ Handle<Code> handler = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler;
@@ -290,7 +286,7 @@
Handle<JSObject> receiver,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub;
@@ -337,7 +333,7 @@
}
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
if (!stub.is_null()) return stub;
@@ -354,7 +350,7 @@
Handle<JSObject> holder,
Handle<JSFunction> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> handler = FindStub(
+ Handle<Code> handler = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
if (!handler.is_null()) return handler;
@@ -369,7 +365,7 @@
Handle<JSObject> receiver,
Handle<JSObject> holder) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
if (!stub.is_null()) return stub;
@@ -387,7 +383,7 @@
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
- Handle<Code> stub = FindStub(
+ Handle<Code> stub = FindHandler(
name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
if (!stub.is_null()) return stub;
@@ -405,12 +401,11 @@
Handle<Map> transition,
StrictModeFlag strict_mode) {
Code::StubType type =
- (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode, type);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ transition.is_null() ? Code::FIELD : Code::MAP_TRANSITION;
+
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::STORE_IC, type, strict_mode);
+ if (!stub.is_null()) return stub;
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code =
@@ -473,11 +468,9 @@
Handle<GlobalObject> receiver,
Handle<JSGlobalPropertyCell> cell,
StrictModeFlag strict_mode) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::STORE_IC, Code::NORMAL, strict_mode);
+ if (!stub.is_null()) return stub;
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
@@ -493,11 +486,9 @@
Handle<ExecutableAccessorInfo> callback,
StrictModeFlag strict_mode) {
ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode, Code::CALLBACKS);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
+ if (!stub.is_null()) return stub;
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code =
@@ -512,11 +503,9 @@
Handle<JSObject> holder,
Handle<JSFunction> setter,
StrictModeFlag strict_mode) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode, Code::CALLBACKS);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
+ if (!stub.is_null()) return stub;
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code =
@@ -529,11 +518,9 @@
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
Handle<JSObject> receiver,
StrictModeFlag strict_mode) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode, Code::INTERCEPTOR);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
+ if (!stub.is_null()) return stub;
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
@@ -548,11 +535,9 @@
StrictModeFlag strict_mode) {
Code::StubType type =
(transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION;
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::KEYED_STORE_IC, strict_mode, type);
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
- isolate_);
- if (probe->IsCode()) return Handle<Code>::cast(probe);
+ Handle<Code> stub = FindIC(
+ name, receiver, Code::KEYED_STORE_IC, type, strict_mode);
+ if (!stub.is_null()) return stub;
KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
Handle<Code> code =
@@ -1452,16 +1437,29 @@
Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
LoadFieldStub stub(reg, field.is_inobject(holder), field.translate(holder));
- GenerateTailCall(stub.GetCode(isolate()));
+ GenerateTailCall(masm(), stub.GetCode(isolate()));
__ bind(&miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
return GetCode(kind(), Code::FIELD, name);
}
+// Load a fast property out of a holder object (src). In-object properties
+// are loaded directly otherwise the property is loaded from the properties
+// fixed array.
+void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
+ Register dst,
+ Register src,
+ Handle<JSObject> holder,
+ PropertyIndex index) {
+ DoGenerateFastPropertyLoad(
+ masm, dst, src, index.is_inobject(holder), index.translate(holder));
+}
+
+
Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object,
Handle<JSObject> holder,
@@ -1527,7 +1525,7 @@
LoadFieldStub stub(interceptor_reg,
field.is_inobject(holder),
field.translate(holder));
- GenerateTailCall(stub.GetCode(isolate()));
+ GenerateTailCall(masm(), stub.GetCode(isolate()));
} else {
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
@@ -1581,9 +1579,110 @@
}
+Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
+ int index,
+ Handle<Map> transition,
+ Handle<Name> name) {
+ Label miss, miss_restore_name;
+
+ GenerateNameCheck(name, this->name(), &miss);
+
+ // Generate store field code.
+ GenerateStoreField(masm(),
+ object,
+ index,
+ transition,
+ name,
+ receiver(), this->name(), value(), scratch1(), scratch2(),
+ &miss,
+ &miss_restore_name);
+
+ // Handle store cache miss.
+ GenerateRestoreName(masm(), &miss_restore_name, name);
+ __ bind(&miss);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
+
+ // Return the generated code.
+ return GetICCode(kind(),
+ transition.is_null() ? Code::FIELD : Code::MAP_TRANSITION,
+ name);
+}
+
+
+Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
+ Handle<Name> name,
+ Handle<JSObject> object,
+ Handle<JSObject> holder,
+ Handle<JSFunction> setter) {
+ Label miss, miss_restore_name;
+
+ // Check that the maps haven't changed, preserving the name register.
+ __ JumpIfSmi(receiver(), &miss);
+ CheckPrototypes(object, receiver(), holder,
+ this->name(), scratch1(), scratch2(),
+ name, &miss_restore_name);
+
+ GenerateStoreViaSetter(masm(), setter);
+
+ GenerateRestoreName(masm(), &miss_restore_name, name);
+
+ __ bind(&miss);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
+
+ // Return the generated code.
+ return GetICCode(kind(), Code::CALLBACKS, name);
+}
+
+
+Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
+ Handle<Map> receiver_map) {
+ ElementsKind elements_kind = receiver_map->elements_kind();
+ if (receiver_map->has_fast_elements() ||
+ receiver_map->has_external_array_elements()) {
+ Handle<Code> stub = KeyedLoadFastElementStub(
+ receiver_map->instance_type() == JS_ARRAY_TYPE,
+ elements_kind).GetCode(isolate());
+ __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
+ } else {
+ Handle<Code> stub =
+ KeyedLoadDictionaryElementStub().GetCode(isolate());
+ __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
+ }
+
+ TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
+
+ // Return the generated code.
+ return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
+}
+
+
+Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
+ Handle<Map> receiver_map) {
+ ElementsKind elements_kind = receiver_map->elements_kind();
+ bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
+ Handle<Code> stub =
+ KeyedStoreElementStub(is_jsarray,
+ elements_kind,
+ store_mode_).GetCode(isolate());
+
+ __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
+
+ TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
+
+ // Return the generated code.
+ return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
+}
+
+
#undef __
+void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
+ Handle<Code> code(masm->isolate()->builtins()->builtin(name));
+ GenerateTailCall(masm, code);
+}
+
+
void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
}
@@ -1594,6 +1693,16 @@
}
+void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
+ GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
+}
+
+
+void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
+ GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
+}
+
+
Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
Code::StubType type,
Handle<Name> name,
@@ -1620,6 +1729,32 @@
}
+Handle<Code> BaseStoreStubCompiler::GetICCode(Code::Kind kind,
+ Code::StubType type,
+ Handle<Name> name,
+ InlineCacheState state) {
+ Code::Flags flags = Code::ComputeFlags(
+ kind, state, extra_state(), type);
+ Handle<Code> code = GetCodeWithFlags(flags, name);
+ PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
+ JitEvent(name, code);
+ return code;
+}
+
+
+Handle<Code> BaseStoreStubCompiler::GetCode(Code::Kind kind,
+ Code::StubType type,
+ Handle<Name> name) {
+ ASSERT(type != Code::NORMAL);
+ Code::Flags flags = Code::ComputeFlags(
+ Code::STUB, MONOMORPHIC, extra_state(), type, kind);
+ Handle<Code> code = GetCodeWithFlags(flags, name);
+ PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
+ JitEvent(name, code);
+ return code;
+}
+
+
void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
CodeHandleList* handlers) {
for (int i = 0; i < receiver_maps->length(); ++i) {
@@ -1648,31 +1783,6 @@
}
-Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
- Handle<Name> name) {
- Code::Flags flags = Code::ComputeMonomorphicFlags(
- Code::STORE_IC, strict_mode_, type);
- Handle<Code> code = GetCodeWithFlags(flags, name);
- PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
- GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
- return code;
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
- Handle<Name> name,
- InlineCacheState state) {
- Code::ExtraICState extra_state =
- Code::ComputeExtraICState(store_mode_, strict_mode_);
- Code::Flags flags =
- Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
- Handle<Code> code = GetCodeWithFlags(flags, name);
- PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
- GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
- return code;
-}
-
-
Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
MapHandleList* receiver_maps) {
// Collect MONOMORPHIC stubs for all |receiver_maps|.
@@ -1696,7 +1806,7 @@
elements_kind,
transitioned_map->elements_kind(),
is_js_array,
- strict_mode_,
+ strict_mode(),
store_mode_).GetCode(isolate());
} else {
cached_stub = KeyedStoreElementStub(
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 56e3d4f..7c45566 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -80,12 +80,15 @@
Handle<Code> FindIC(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
- Code::StubType type);
+ Code::StubType type,
+ Code::ExtraICState extra_state = Code::kNoExtraICState);
- Handle<Code> FindStub(Handle<Name> name,
- Handle<JSObject> stub_holder,
- Code::Kind kind,
- Code::StubType type);
+ Handle<Code> FindHandler(
+ Handle<Name> name,
+ Handle<JSObject> stub_holder,
+ Code::Kind kind,
+ Code::StubType type,
+ Code::ExtraICState extra_state = Code::kNoExtraICState);
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
Handle<Code> handler,
@@ -513,14 +516,23 @@
Handle<Name> name,
Register receiver_reg,
Register name_reg,
+ Register value_reg,
Register scratch1,
Register scratch2,
- Label* miss_label);
+ Label* miss_label,
+ Label* miss_restore_name);
- static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
- static void GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind);
-
- static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
+ static Builtins::Name MissBuiltin(Code::Kind kind) {
+ switch (kind) {
+ case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
+ case Code::STORE_IC: return Builtins::kStoreIC_Miss;
+ case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
+ case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
+ default: UNREACHABLE();
+ }
+ return Builtins::kLoadIC_Miss;
+ }
+ static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
// Generates code that verifies that the property holder has not changed
// (checking maps of objects in the prototype chain for fast and global
@@ -577,7 +589,7 @@
Heap* heap() { return isolate()->heap(); }
Factory* factory() { return isolate()->factory(); }
- void GenerateTailCall(Handle<Code> code);
+ static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
private:
Isolate* isolate_;
@@ -739,8 +751,6 @@
void CompileElementHandlers(MapHandleList* receiver_maps,
CodeHandleList* handlers);
- Handle<Code> CompileLoadElementPolymorphic(MapHandleList* receiver_maps);
-
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
static Register receiver() { return registers()[0]; }
@@ -760,17 +770,63 @@
};
-class StoreStubCompiler: public StubCompiler {
+class BaseStoreStubCompiler: public StubCompiler {
public:
- StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
- : StubCompiler(isolate), strict_mode_(strict_mode) { }
+ BaseStoreStubCompiler(Isolate* isolate,
+ StrictModeFlag strict_mode,
+ Register* registers)
+ : StubCompiler(isolate),
+ strict_mode_(strict_mode),
+ registers_(registers) { }
+ virtual ~BaseStoreStubCompiler() { }
Handle<Code> CompileStoreField(Handle<JSObject> object,
int index,
Handle<Map> transition,
Handle<Name> name);
+ protected:
+ Handle<Code> GetICCode(Code::Kind kind,
+ Code::StubType type,
+ Handle<Name> name,
+ InlineCacheState state = MONOMORPHIC);
+
+ Handle<Code> GetCode(Code::Kind kind,
+ Code::StubType type,
+ Handle<Name> name);
+
+ void GenerateRestoreName(MacroAssembler* masm,
+ Label* label,
+ Handle<Name> name);
+
+ Register receiver() { return registers_[0]; }
+ Register name() { return registers_[1]; }
+ Register value() { return registers_[2]; }
+ Register scratch1() { return registers_[3]; }
+ Register scratch2() { return registers_[4]; }
+ Register scratch3() { return registers_[5]; }
+ StrictModeFlag strict_mode() { return strict_mode_; }
+ virtual Code::ExtraICState extra_state() { return strict_mode_; }
+
+ private:
+ virtual Code::Kind kind() = 0;
+ virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
+ virtual void GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss) { }
+ StrictModeFlag strict_mode_;
+ Register* registers_;
+};
+
+
+class StoreStubCompiler: public BaseStoreStubCompiler {
+ public:
+ StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
+ : BaseStoreStubCompiler(isolate, strict_mode, registers()) { }
+
+
Handle<Code> CompileStoreCallback(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
@@ -792,25 +848,24 @@
Handle<Name> name);
private:
- Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
-
- StrictModeFlag strict_mode_;
+ static Register* registers();
+ virtual Code::Kind kind() { return Code::STORE_IC; }
+ virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
+ if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
+ return code->ic_state() == MONOMORPHIC
+ ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
+ }
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code);
};
-class KeyedStoreStubCompiler: public StubCompiler {
+class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
public:
KeyedStoreStubCompiler(Isolate* isolate,
StrictModeFlag strict_mode,
KeyedAccessStoreMode store_mode)
- : StubCompiler(isolate),
- strict_mode_(strict_mode),
- store_mode_(store_mode) { }
-
- Handle<Code> CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name);
+ : BaseStoreStubCompiler(isolate, strict_mode, registers()),
+ store_mode_(store_mode) { }
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
@@ -834,12 +889,27 @@
static void GenerateStoreDictionaryElement(MacroAssembler* masm);
- private:
- Handle<Code> GetCode(Code::StubType type,
- Handle<Name> name,
- InlineCacheState state = MONOMORPHIC);
+ protected:
+ virtual Code::ExtraICState extra_state() {
+ return Code::ComputeExtraICState(store_mode_, strict_mode());
+ }
- StrictModeFlag strict_mode_;
+ private:
+ Register transition_map() {
+ return registers()[3];
+ }
+
+ static Register* registers();
+ virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
+ virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
+ if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
+ return code->ic_state() == MONOMORPHIC
+ ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
+ }
+ virtual void JitEvent(Handle<Name> name, Handle<Code> code);
+ virtual void GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss);
KeyedAccessStoreMode store_mode_;
};
diff --git a/src/unicode-inl.h b/src/unicode-inl.h
index c80c67e..02be457 100644
--- a/src/unicode-inl.h
+++ b/src/unicode-inl.h
@@ -95,6 +95,18 @@
}
+unsigned Utf8::EncodeOneByte(char* str, uint8_t c) {
+ static const int kMask = ~(1 << 6);
+ if (c <= kMaxOneByteChar) {
+ str[0] = c;
+ return 1;
+ }
+ str[0] = 0xC0 | (c >> 6);
+ str[1] = 0x80 | (c & kMask);
+ return 2;
+}
+
+
unsigned Utf8::Encode(char* str, uchar c, int previous) {
static const int kMask = ~(1 << 6);
if (c <= kMaxOneByteChar) {
diff --git a/src/unicode.h b/src/unicode.h
index f8a1f60..42a8182 100644
--- a/src/unicode.h
+++ b/src/unicode.h
@@ -135,11 +135,7 @@
class Latin1 {
public:
-#ifndef ENABLE_LATIN_1
- static const unsigned kMaxChar = 0x7f;
-#else
static const unsigned kMaxChar = 0xff;
-#endif
// Returns 0 if character does not convert to single latin-1 character
// or if the character doesn't not convert back to latin-1 via inverse
// operation (upper to lower, etc).
@@ -149,6 +145,7 @@
class Utf8 {
public:
static inline uchar Length(uchar chr, int previous);
+ static inline unsigned EncodeOneByte(char* out, uint8_t c);
static inline unsigned Encode(
char* out, uchar c, int previous);
static uchar CalculateValue(const byte* str,
diff --git a/src/v8.cc b/src/v8.cc
index 1753650..2e8cd50 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -268,6 +268,7 @@
FLAG_gc_global = true;
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
}
+ if (FLAG_trace_hydrogen) FLAG_parallel_recompilation = false;
OS::SetUp();
CPU::SetUp();
use_crankshaft_ = FLAG_crankshaft
diff --git a/src/version.cc b/src/version.cc
index b3e5c45..919c8a3 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 17
-#define BUILD_NUMBER 10
+#define BUILD_NUMBER 11
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 7a1e88f..0b70c1a 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -1118,12 +1118,7 @@
if (initial_capacity > 0) {
size += FixedArray::SizeFor(initial_capacity);
}
- __ AllocateInNewSpace(size,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT);
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
@@ -1646,12 +1641,12 @@
// Allocate a JSValue and put the tagged pointer into rax.
Label gc_required;
- __ AllocateInNewSpace(JSValue::kSize,
- rax, // Result.
- rcx, // New allocation top (we ignore it).
- no_reg,
- &gc_required,
- TAG_OBJECT);
+ __ Allocate(JSValue::kSize,
+ rax, // Result.
+ rcx, // New allocation top (we ignore it).
+ no_reg,
+ &gc_required,
+ TAG_OBJECT);
// Set the map.
__ LoadGlobalFunctionInitialMap(rdi, rcx);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 7ebc103..04c3e68 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -140,7 +140,7 @@
Counters* counters = masm->isolate()->counters();
Label gc;
- __ AllocateInNewSpace(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
+ __ Allocate(JSFunction::kSize, rax, rbx, rcx, &gc, TAG_OBJECT);
__ IncrementCounter(counters->fast_new_closure_total(), 1);
@@ -274,8 +274,8 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
- rax, rbx, rcx, &gc, TAG_OBJECT);
+ __ Allocate((length * kPointerSize) + FixedArray::kHeaderSize,
+ rax, rbx, rcx, &gc, TAG_OBJECT);
// Get the function from the stack.
__ movq(rcx, Operand(rsp, 1 * kPointerSize));
@@ -320,8 +320,8 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- rax, rbx, rcx, &gc, TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length),
+ rax, rbx, rcx, &gc, TAG_OBJECT);
// Get the function from the stack.
__ movq(rcx, Operand(rsp, 1 * kPointerSize));
@@ -406,7 +406,7 @@
if (mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS) {
flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT | flags);
}
- __ AllocateInNewSpace(size, rax, rbx, rdx, fail, flags);
+ __ Allocate(size, rax, rbx, rdx, fail, flags);
if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
__ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex);
@@ -1316,12 +1316,8 @@
// Allocate heap number in new space.
// Not using AllocateHeapNumber macro in order to reuse
// already loaded heap_number_map.
- __ AllocateInNewSpace(HeapNumber::kSize,
- rax,
- rdx,
- no_reg,
- &allocation_failed,
- TAG_OBJECT);
+ __ Allocate(HeapNumber::kSize, rax, rdx, no_reg, &allocation_failed,
+ TAG_OBJECT);
// Set the map.
__ AssertRootValue(heap_number_map,
Heap::kHeapNumberMapRootIndex,
@@ -2403,7 +2399,7 @@
StubCompiler::GenerateLoadArrayLength(masm, receiver, r8, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -2431,7 +2427,7 @@
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -2460,7 +2456,7 @@
StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
support_wrapper_);
__ bind(&miss);
- StubCompiler::GenerateLoadMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -2523,7 +2519,7 @@
__ bind(&miss);
- StubCompiler::GenerateStoreMiss(masm, kind());
+ StubCompiler::TailCallBuiltin(masm, StubCompiler::MissBuiltin(kind()));
}
@@ -5756,32 +5752,22 @@
// Compare lengths (precomputed).
__ bind(&compare_lengths);
__ SmiTest(length_difference);
-#ifndef ENABLE_LATIN_1
- __ j(not_zero, &result_not_equal, Label::kNear);
-#else
Label length_not_equal;
__ j(not_zero, &length_not_equal, Label::kNear);
-#endif
// Result is EQUAL.
__ Move(rax, Smi::FromInt(EQUAL));
__ ret(0);
Label result_greater;
-#ifdef ENABLE_LATIN_1
Label result_less;
__ bind(&length_not_equal);
__ j(greater, &result_greater, Label::kNear);
__ jmp(&result_less, Label::kNear);
-#endif
__ bind(&result_not_equal);
// Unequal comparison of left to right, either character or length.
-#ifndef ENABLE_LATIN_1
- __ j(greater, &result_greater, Label::kNear);
-#else
__ j(above, &result_greater, Label::kNear);
__ bind(&result_less);
-#endif
// Result is LESS.
__ Move(rax, Smi::FromInt(LESS));
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index ee510eb..8ff12df 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1514,7 +1514,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index b185684..0a9ceaa 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -1333,8 +1333,7 @@
Isolate::Current()->stub_cache()->GenerateProbe(
masm, flags, rax, rcx, rbx, rdx);
- // Cache miss: Jump to runtime.
- StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
+ GenerateMiss(masm);
}
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index cf78698..3d167ef 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -3949,6 +3949,13 @@
}
+void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
+ Register result = ToRegister(instr->result());
+ Register base = ToRegister(instr->base_object());
+ __ lea(result, Operand(base, instr->offset()));
+}
+
+
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register object = ToRegister(instr->object());
Register value = ToRegister(instr->value());
@@ -5025,12 +5032,8 @@
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
- __ AllocateInNewSpace(instance_size,
- result,
- no_reg,
- scratch,
- deferred->entry(),
- TAG_OBJECT);
+ __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
+ TAG_OBJECT);
__ bind(deferred->exit());
if (FLAG_debug_code) {
@@ -5119,7 +5122,10 @@
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
+ if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+ flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+ }
+ __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ AllocateInNewSpace(size, result, temp, no_reg, deferred->entry(), flags);
@@ -5340,7 +5346,7 @@
// Allocate all objects that are part of the literal in one big
// allocation. This avoids multiple limit checks.
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
@@ -5427,7 +5433,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 009df37..d9c2f95 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -292,6 +292,13 @@
}
+void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ base_object()->PrintTo(stream);
+ stream->Add(" + %d", offset());
+}
+
+
void LCallConstantFunction::PrintDataTo(StringStream* stream) {
stream->Add("#%d / ", arity());
}
@@ -676,8 +683,12 @@
LUnallocated* LChunkBuilder::TempRegister() {
LUnallocated* operand =
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
- operand->set_virtual_register(allocator_->GetVirtualRegister());
- if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
+ int vreg = allocator_->GetVirtualRegister();
+ if (!allocator_->AllocationOk()) {
+ Abort("Out of virtual registers while trying to allocate temp register.");
+ return NULL;
+ }
+ operand->set_virtual_register(vreg);
return operand;
}
@@ -938,7 +949,7 @@
if (value->EmitAtUses()) {
ASSERT(value->IsConstant());
ASSERT(!value->representation().IsDouble());
- HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
+ HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
? instr->FirstSuccessor()
: instr->SecondSuccessor();
return new(zone()) LGoto(successor->block_id());
@@ -1024,6 +1035,15 @@
}
+LInstruction* LChunkBuilder::DoInnerAllocatedObject(
+ HInnerAllocatedObject* inner_object) {
+ LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
+ LInnerAllocatedObject* result =
+ new(zone()) LInnerAllocatedObject(base_object);
+ return DefineAsRegister(result);
+}
+
+
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
return instr->HasNoUses()
? NULL
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 22a1f96..9e3e836 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -188,7 +188,8 @@
V(LoadFieldByIndex) \
V(DateField) \
V(WrapReceiver) \
- V(Drop)
+ V(Drop) \
+ V(InnerAllocatedObject)
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
@@ -1594,6 +1595,22 @@
};
+class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LInnerAllocatedObject(LOperand* base_object) {
+ inputs_[0] = base_object;
+ }
+
+ LOperand* base_object() { return inputs_[0]; }
+ int offset() { return hydrogen()->offset(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object")
+ DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject)
+};
+
+
class LThisFunction: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 5a263ab..9ecf66c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -551,7 +551,8 @@
void MacroAssembler::TailCallStub(CodeStub* stub) {
- ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+ ASSERT(allow_stub_calls_ ||
+ stub->CompilingCallsToThisStubIsGCSafe(isolate()));
Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET);
}
@@ -564,7 +565,7 @@
bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
- return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
+ return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(isolate());
}
@@ -2943,6 +2944,7 @@
void MacroAssembler::DispatchMap(Register obj,
+ Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type) {
@@ -3714,8 +3716,8 @@
void MacroAssembler::LoadAllocationTopHelper(Register result,
Register scratch,
AllocationFlags flags) {
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
// Just return if allocation top is already known.
if ((flags & RESULT_CONTAINS_TOP) != 0) {
@@ -3723,7 +3725,7 @@
ASSERT(!scratch.is_valid());
#ifdef DEBUG
// Assert that result actually contains top on entry.
- Operand top_operand = ExternalOperand(new_space_allocation_top);
+ Operand top_operand = ExternalOperand(allocation_top);
cmpq(result, top_operand);
Check(equal, "Unexpected allocation top");
#endif
@@ -3733,40 +3735,41 @@
// Move address of new object to result. Use scratch register if available,
// and keep address in scratch until call to UpdateAllocationTopHelper.
if (scratch.is_valid()) {
- LoadAddress(scratch, new_space_allocation_top);
+ LoadAddress(scratch, allocation_top);
movq(result, Operand(scratch, 0));
} else {
- Load(result, new_space_allocation_top);
+ Load(result, allocation_top);
}
}
void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
- Register scratch) {
+ Register scratch,
+ AllocationFlags flags) {
if (emit_debug_code()) {
testq(result_end, Immediate(kObjectAlignmentMask));
Check(zero, "Unaligned allocation in new space");
}
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
// Update new top.
if (scratch.is_valid()) {
// Scratch already contains address of allocation top.
movq(Operand(scratch, 0), result_end);
} else {
- Store(new_space_allocation_top, result_end);
+ Store(allocation_top, result_end);
}
}
-void MacroAssembler::AllocateInNewSpace(int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
@@ -3795,8 +3798,8 @@
}
// Calculate new top and bail out if new space is exhausted.
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
Register top_reg = result_end.is_valid() ? result_end : result;
@@ -3805,12 +3808,12 @@
}
addq(top_reg, Immediate(object_size));
j(carry, gc_required);
- Operand limit_operand = ExternalOperand(new_space_allocation_limit);
+ Operand limit_operand = ExternalOperand(allocation_limit);
cmpq(top_reg, limit_operand);
j(above, gc_required);
// Update allocation top.
- UpdateAllocationTopHelper(top_reg, scratch);
+ UpdateAllocationTopHelper(top_reg, scratch, flags);
bool tag_result = (flags & TAG_OBJECT) != 0;
if (top_reg.is(result)) {
@@ -3836,6 +3839,7 @@
Label* gc_required,
AllocationFlags flags) {
ASSERT((flags & SIZE_IN_WORDS) == 0);
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3875,7 +3879,7 @@
j(above, gc_required);
// Update allocation top.
- UpdateAllocationTopHelper(result_end, scratch);
+ UpdateAllocationTopHelper(result_end, scratch, flags);
// Tag the result if requested.
if ((flags & TAG_OBJECT) != 0) {
@@ -3892,6 +3896,7 @@
Label* gc_required,
AllocationFlags flags) {
ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3923,7 +3928,7 @@
j(above, gc_required);
// Update allocation top.
- UpdateAllocationTopHelper(result_end, scratch);
+ UpdateAllocationTopHelper(result_end, scratch, flags);
// Align the next allocation. Storing the filler map without checking top is
// always safe because the limit of the heap is always aligned.
@@ -3958,12 +3963,7 @@
Register scratch,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(HeapNumber::kSize,
- result,
- scratch,
- no_reg,
- gc_required,
- TAG_OBJECT);
+ Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required, TAG_OBJECT);
// Set the map.
LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
@@ -4053,12 +4053,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
@@ -4071,12 +4067,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
@@ -4089,12 +4081,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
LoadRoot(kScratchRegister, Heap::kSlicedStringMapRootIndex);
@@ -4107,12 +4095,8 @@
Register scratch2,
Label* gc_required) {
// Allocate heap number in new space.
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
// Set the map. The other fields are left uninitialized.
LoadRoot(kScratchRegister, Heap::kSlicedAsciiStringMapRootIndex);
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 7827feb..df52159 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -909,6 +909,7 @@
// specified target if equal. Skip the smi check if not required (object is
// known to be a heap object)
void DispatchMap(Register obj,
+ Register unused,
Handle<Map> map,
Handle<Code> success,
SmiCheckType smi_check_type);
@@ -1024,22 +1025,22 @@
// ---------------------------------------------------------------------------
// Allocation support
- // Allocate an object in new space. If the new space is exhausted control
- // continues at the gc_required label. The allocated object is returned in
- // result and end of the new object is returned in result_end. The register
- // scratch can be passed as no_reg in which case an additional object
- // reference will be added to the reloc info. The returned pointers in result
- // and result_end have not yet been tagged as heap objects. If
- // result_contains_top_on_entry is true the content of result is known to be
- // the allocation top on entry (could be result_end from a previous call to
- // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
+ // Allocate an object in new space or old pointer space. If the given space
+ // is exhausted control continues at the gc_required label. The allocated
+ // object is returned in result and end of the new object is returned in
+ // result_end. The register scratch can be passed as no_reg in which case
+ // an additional object reference will be added to the reloc info. The
+ // returned pointers in result and result_end have not yet been tagged as
+ // heap objects. If result_contains_top_on_entry is true the content of
+ // result is known to be the allocation top on entry (could be result_end
+ // from a previous call). If result_contains_top_on_entry is true scratch
// should be no_reg as it is never used.
- void AllocateInNewSpace(int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- AllocationFlags flags);
+ void Allocate(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags);
void AllocateInNewSpace(int header_size,
ScaleFactor element_size,
@@ -1388,9 +1389,12 @@
void LoadAllocationTopHelper(Register result,
Register scratch,
AllocationFlags flags);
+
// Update allocation top with value in result_end register.
// If scratch is valid, it contains the address of the allocation top.
- void UpdateAllocationTopHelper(Register result_end, Register scratch);
+ void UpdateAllocationTopHelper(Register result_end,
+ Register scratch,
+ AllocationFlags flags);
// Helper for PopHandleScope. Allowed to perform a GC and returns
// NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index c9871f0..914241e 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -393,9 +393,6 @@
__ j(not_equal, on_no_match); // Definitely not equal.
__ subb(rax, Immediate('a'));
__ cmpb(rax, Immediate('z' - 'a'));
-#ifndef ENABLE_LATIN_1
- __ j(above, on_no_match); // Weren't letters anyway.
-#else
__ j(below_equal, &loop_increment); // In range 'a'-'z'.
// Latin-1: Check for values in range [224,254] but not 247.
__ subb(rax, Immediate(224 - 'a'));
@@ -403,7 +400,6 @@
__ j(above, on_no_match); // Weren't Latin-1 letters.
__ cmpb(rax, Immediate(247 - 224)); // Check for 247.
__ j(equal, on_no_match);
-#endif
__ bind(&loop_increment);
// Increment pointers into match and capture strings.
__ addq(r11, Immediate(1));
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 0e8e74e..69d7a91 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -343,19 +343,6 @@
}
-// Load a fast property out of a holder object (src). In-object properties
-// are loaded directly otherwise the property is loaded from the properties
-// fixed array.
-void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst,
- Register src,
- Handle<JSObject> holder,
- PropertyIndex index) {
- DoGenerateFastPropertyLoad(
- masm, dst, src, index.is_inobject(holder), index.translate(holder));
-}
-
-
void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm,
Register dst,
Register src,
@@ -715,28 +702,13 @@
};
-void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
- Handle<Code> code = (kind == Code::LOAD_IC)
- ? masm->isolate()->builtins()->LoadIC_Miss()
- : masm->isolate()->builtins()->KeyedLoadIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
- ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
- Handle<Code> code = (kind == Code::STORE_IC)
- ? masm->isolate()->builtins()->StoreIC_Miss()
- : masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
-void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
- Handle<Code> code =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ Jump(code, RelocInfo::CODE_TARGET);
+void BaseStoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
+ Label* label,
+ Handle<Name> name) {
+ if (!label->is_unused()) {
+ __ bind(label);
+ __ Move(this->name(), name);
+ }
}
@@ -749,9 +721,11 @@
Handle<Name> name,
Register receiver_reg,
Register name_reg,
+ Register value_reg,
Register scratch1,
Register scratch2,
- Label* miss_label) {
+ Label* miss_label,
+ Label* miss_restore_name) {
LookupResult lookup(masm->isolate());
object->Lookup(*name, &lookup);
if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) {
@@ -785,17 +759,8 @@
holder = JSObject::cast(holder->GetPrototype());
} while (holder->GetPrototype()->IsJSObject());
}
- // We need an extra register, push
- __ push(name_reg);
- Label miss_pop, done_check;
CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg,
- scratch1, scratch2, name, &miss_pop);
- __ jmp(&done_check);
- __ bind(&miss_pop);
- __ pop(name_reg);
- __ jmp(miss_label);
- __ bind(&done_check);
- __ pop(name_reg);
+ scratch1, scratch2, name, miss_restore_name);
}
// Stub never generated for non-global objects that require access
@@ -809,7 +774,7 @@
__ pop(scratch1); // Return address.
__ push(receiver_reg);
__ Push(transition);
- __ push(rax);
+ __ push(value_reg);
__ push(scratch1);
__ TailCallExternalReference(
ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
@@ -843,11 +808,11 @@
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movq(FieldOperand(receiver_reg, offset), rax);
+ __ movq(FieldOperand(receiver_reg, offset), value_reg);
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, rax);
+ __ movq(name_reg, value_reg);
__ RecordWriteField(
receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
} else {
@@ -855,16 +820,17 @@
int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
__ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ movq(FieldOperand(scratch1, offset), rax);
+ __ movq(FieldOperand(scratch1, offset), value_reg);
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, rax);
+ __ movq(name_reg, value_reg);
__ RecordWriteField(
scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
}
// Return the value (register rax).
+ ASSERT(value_reg.is(rax));
__ ret(0);
}
@@ -908,15 +874,16 @@
}
}
-#undef __
-#define __ ACCESS_MASM((masm()))
-
-void StubCompiler::GenerateTailCall(Handle<Code> code) {
+void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
__ jmp(code, RelocInfo::CODE_TARGET);
}
+#undef __
+#define __ ACCESS_MASM((masm()))
+
+
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
Register object_reg,
Handle<JSObject> holder,
@@ -1039,7 +1006,7 @@
if (!miss->is_unused()) {
__ jmp(success);
__ bind(miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
}
}
@@ -2408,64 +2375,26 @@
}
-Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Generate store field code. Preserves receiver and name on jump to miss.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- rdx, rcx, rbx, rdi,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
Label miss;
// Check that the maps haven't changed.
- __ JumpIfSmi(rdx, &miss);
- CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss);
+ __ JumpIfSmi(receiver(), &miss);
+ CheckPrototypes(object, receiver(), holder,
+ scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
- __ pop(rbx); // remove the return address
- __ push(rdx); // receiver
+ __ pop(scratch1()); // remove the return address
+ __ push(receiver());
__ Push(callback); // callback info
- __ push(rcx); // name
- __ push(rax); // value
- __ push(rbx); // restore return address
+ __ push(this->name());
+ __ push(value());
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@@ -2474,11 +2403,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::CALLBACKS, name);
+ return GetICCode(kind(), Code::CALLBACKS, name);
}
@@ -2528,64 +2456,30 @@
#define __ ACCESS_MASM(masm())
-Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<Name> name,
- Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<JSFunction> setter) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check that the maps haven't changed.
- __ JumpIfSmi(rdx, &miss);
- CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss);
-
- GenerateStoreViaSetter(masm(), setter);
-
- __ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::CALLBACKS, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
- __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss,
+ __ CheckMap(receiver(), Handle<Map>(object->map()), &miss,
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
- if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(rdx, rbx, &miss);
+ if (object->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
}
// Stub never generated for non-global objects that require access
// checks.
- ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- __ pop(rbx); // remove the return address
- __ push(rdx); // receiver
- __ push(rcx); // name
- __ push(rax); // value
- __ Push(Smi::FromInt(strict_mode_));
- __ push(rbx); // restore return address
+ __ pop(scratch1()); // remove the return address
+ __ push(receiver());
+ __ push(this->name());
+ __ push(value());
+ __ Push(Smi::FromInt(strict_mode()));
+ __ push(scratch1()); // restore return address
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@@ -2594,11 +2488,10 @@
// Handle store cache miss.
__ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::INTERCEPTOR, name);
+ return GetICCode(kind(), Code::INTERCEPTOR, name);
}
@@ -2606,22 +2499,17 @@
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
+ __ Cmp(FieldOperand(receiver(), HeapObject::kMapOffset),
Handle<Map>(object->map()));
__ j(not_equal, &miss);
// Compute the cell operand to use.
- __ Move(rbx, cell);
- Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset);
+ __ Move(scratch1(), cell);
+ Operand cell_operand =
+ FieldOperand(scratch1(), JSGlobalPropertyCell::kValueOffset);
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
@@ -2631,7 +2519,7 @@
__ j(equal, &miss);
// Store the value in the cell.
- __ movq(cell_operand, rax);
+ __ movq(cell_operand, value());
// Cells are always rescanned, so no write barrier here.
// Return the value (register rax).
@@ -2642,78 +2530,10 @@
// Handle store cache miss.
__ bind(&miss);
__ IncrementCounter(counters->named_store_global_inline_miss(), 1);
- Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, name);
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
- int index,
- Handle<Map> transition,
- Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- Label miss;
-
- Counters* counters = isolate()->counters();
- __ IncrementCounter(counters->keyed_store_field(), 1);
-
- // Check that the name has not changed.
- __ Cmp(rcx, name);
- __ j(not_equal, &miss);
-
- // Generate store field code. Preserves receiver and name on jump to miss.
- GenerateStoreField(masm(),
- object,
- index,
- transition,
- name,
- rdx, rcx, rbx, rdi,
- &miss);
-
- // Handle store cache miss.
- __ bind(&miss);
- __ DecrementCounter(counters->keyed_store_field(), 1);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(transition.is_null()
- ? Code::FIELD
- : Code::MAP_TRANSITION, name);
-}
-
-
-Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
-
- ElementsKind elements_kind = receiver_map->elements_kind();
- bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
- Handle<Code> stub =
- KeyedStoreElementStub(is_js_array,
- elements_kind,
- store_mode_).GetCode(isolate());
-
- __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
-
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string());
+ return GetICCode(kind(), Code::NORMAL, name);
}
@@ -2721,37 +2541,34 @@
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
Label miss;
- __ JumpIfSmi(rdx, &miss, Label::kNear);
+ __ JumpIfSmi(receiver(), &miss, Label::kNear);
- __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ movq(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
for (int i = 0; i < receiver_count; ++i) {
// Check map and tail call if there's a match
- __ Cmp(rdi, receiver_maps->at(i));
+ __ Cmp(scratch1(), receiver_maps->at(i));
if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
} else {
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
- __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT);
+ __ movq(transition_map(),
+ transitioned_maps->at(i),
+ RelocInfo::EMBEDDED_OBJECT);
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
}
__ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
- return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
+ return GetICCode(
+ kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
}
@@ -2789,6 +2606,20 @@
}
+Register* StoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
+ return registers;
+}
+
+
+Register* KeyedStoreStubCompiler::registers() {
+ // receiver, name, value, scratch1, scratch2, scratch3.
+ static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
+ return registers;
+}
+
+
void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
Register name_reg,
Label* miss) {
@@ -2797,6 +2628,14 @@
}
+void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
+ Register name_reg,
+ Label* miss) {
+ __ Cmp(name_reg, name);
+ __ j(not_equal, miss);
+}
+
+
#undef __
#define __ ACCESS_MASM(masm)
@@ -2875,33 +2714,6 @@
}
-Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- rax : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
- Handle<Code> stub = KeyedLoadFastElementStub(
- receiver_map->instance_type() == JS_ARRAY_TYPE,
- elements_kind).GetCode(isolate());
- __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
- } else {
- Handle<Code> stub =
- KeyedLoadDictionaryElementStub().GetCode(isolate());
- __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
- }
-
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
- // Return the generated code.
- return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
@@ -2925,7 +2737,7 @@
}
__ bind(&miss);
- GenerateLoadMiss(masm(), kind());
+ TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
InlineCacheState state =
@@ -2985,8 +2797,8 @@
__ cmpq(rcx, Immediate(instance_size));
__ Check(equal, "Instance size of initial map changed.");
#endif
- __ AllocateInNewSpace(instance_size, rdx, rcx, no_reg,
- &generic_stub_call, NO_ALLOCATION_FLAGS);
+ __ Allocate(instance_size, rdx, rcx, no_reg, &generic_stub_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields and add the heap tag.
// rbx: initial map
@@ -3101,9 +2913,7 @@
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- Handle<Code> slow_ic =
- masm->isolate()->builtins()->KeyedLoadIC_Slow();
- __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
__ bind(&miss_force_generic);
// ----------- S t a t e -------------
@@ -3111,9 +2921,7 @@
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
- __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
}
@@ -3311,9 +3119,7 @@
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
-
- Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
// Miss case: call runtime.
__ bind(&miss_force_generic);
@@ -3324,10 +3130,7 @@
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
-
- Handle<Code> miss_ic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
}
@@ -3396,13 +3199,10 @@
// Handle store cache miss.
__ bind(&miss_force_generic);
- Handle<Code> ic_force_generic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -3420,7 +3220,7 @@
__ j(not_equal, &check_capacity);
int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
+ __ Allocate(size, rdi, rbx, r8, &slow, TAG_OBJECT);
// rax: value
// rcx: key
@@ -3468,8 +3268,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}
@@ -3519,16 +3318,13 @@
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
- Handle<Code> ic_force_generic =
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
- __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
__ bind(&restore_key_transition_elements_kind);
// Restore smi-tagging of rcx.
__ Integer32ToSmi(rcx, rcx);
__ bind(&transition_elements_kind);
- Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic_miss, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
if (is_js_array && IsGrowStoreMode(store_mode)) {
// Grow the array by a single element if possible.
@@ -3554,7 +3350,7 @@
__ j(not_equal, &check_capacity);
int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT);
+ __ Allocate(size, rdi, rbx, r8, &slow, TAG_OBJECT);
// rax: value
// rcx: key
@@ -3602,8 +3398,7 @@
__ jmp(&finish_store);
__ bind(&slow);
- Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
- __ jmp(ic_slow, RelocInfo::CODE_TARGET);
+ TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
}
}