summaryrefslogtreecommitdiffstats
path: root/src/x87
diff options
context:
space:
mode:
authorEmily Bernier <ember@google.com>2015-03-24 16:35:39 -0400
committerEmily Bernier <ember@google.com>2015-06-23 16:55:40 -0400
commit958fae7ec3f466955f8e5b50fa5b8d38b9e91675 (patch)
treea63ee37f93192ad427f88ed926743f6bb6014312 /src/x87
parent57a14c9a8621270b0e6c697dce28a9c453ebe55f (diff)
downloadandroid_external_v8-958fae7ec3f466955f8e5b50fa5b8d38b9e91675.tar.gz
android_external_v8-958fae7ec3f466955f8e5b50fa5b8d38b9e91675.tar.bz2
android_external_v8-958fae7ec3f466955f8e5b50fa5b8d38b9e91675.zip
Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the 4.1.0.21 cherry-pick in Chromium. Original commit message: Version 4.1.0.21 (cherry-pick) Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412 Unlink pages from the space page list after evacuation. BUG=430201 LOG=N R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/953813002 Cr-Commit-Position: refs/branch-heads/4.1@{#22} Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353} --- Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
Diffstat (limited to 'src/x87')
-rw-r--r--src/x87/assembler-x87.cc15
-rw-r--r--src/x87/assembler-x87.h17
-rw-r--r--src/x87/builtins-x87.cc41
-rw-r--r--src/x87/code-stubs-x87.cc192
-rw-r--r--src/x87/code-stubs-x87.h10
-rw-r--r--src/x87/codegen-x87.cc13
-rw-r--r--src/x87/debug-x87.cc6
-rw-r--r--src/x87/deoptimizer-x87.cc2
-rw-r--r--src/x87/disasm-x87.cc6
-rw-r--r--src/x87/full-codegen-x87.cc567
-rw-r--r--src/x87/interface-descriptors-x87.cc12
-rw-r--r--src/x87/lithium-codegen-x87.cc178
-rw-r--r--src/x87/lithium-x87.cc28
-rw-r--r--src/x87/lithium-x87.h166
-rw-r--r--src/x87/macro-assembler-x87.cc56
-rw-r--r--src/x87/macro-assembler-x87.h27
16 files changed, 909 insertions, 427 deletions
diff --git a/src/x87/assembler-x87.cc b/src/x87/assembler-x87.cc
index 9e1c8836..4177156e 100644
--- a/src/x87/assembler-x87.cc
+++ b/src/x87/assembler-x87.cc
@@ -915,24 +915,24 @@ void Assembler::rcr(Register dst, uint8_t imm8) {
}
-void Assembler::ror(Register dst, uint8_t imm8) {
+void Assembler::ror(const Operand& dst, uint8_t imm8) {
EnsureSpace ensure_space(this);
DCHECK(is_uint5(imm8)); // illegal shift count
if (imm8 == 1) {
EMIT(0xD1);
- EMIT(0xC8 | dst.code());
+ emit_operand(ecx, dst);
} else {
EMIT(0xC1);
- EMIT(0xC8 | dst.code());
+ emit_operand(ecx, dst);
EMIT(imm8);
}
}
-void Assembler::ror_cl(Register dst) {
+void Assembler::ror_cl(const Operand& dst) {
EnsureSpace ensure_space(this);
EMIT(0xD3);
- EMIT(0xC8 | dst.code());
+ emit_operand(ecx, dst);
}
@@ -1897,11 +1897,6 @@ void Assembler::setcc(Condition cc, Register reg) {
}
-void Assembler::Print() {
- Disassembler::Decode(isolate(), stdout, buffer_, pc_);
-}
-
-
void Assembler::RecordJSReturn() {
positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this);
diff --git a/src/x87/assembler-x87.h b/src/x87/assembler-x87.h
index d37c9d77..1da632f2 100644
--- a/src/x87/assembler-x87.h
+++ b/src/x87/assembler-x87.h
@@ -148,6 +148,13 @@ struct X87Register {
return kMaxNumAllocatableRegisters;
}
+
+ // TODO(turbofan): Proper support for float32.
+ static int NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+ }
+
+
static int ToAllocationIndex(X87Register reg) {
return reg.code_;
}
@@ -718,8 +725,11 @@ class Assembler : public AssemblerBase {
void rcl(Register dst, uint8_t imm8);
void rcr(Register dst, uint8_t imm8);
- void ror(Register dst, uint8_t imm8);
- void ror_cl(Register dst);
+
+ void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); }
+ void ror(const Operand& dst, uint8_t imm8);
+ void ror_cl(Register dst) { ror_cl(Operand(dst)); }
+ void ror_cl(const Operand& dst);
void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); }
void sar(const Operand& dst, uint8_t imm8);
@@ -909,9 +919,6 @@ class Assembler : public AssemblerBase {
// TODO(lrn): Need SFENCE for movnt?
- // Debugging
- void Print();
-
// Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos();
diff --git a/src/x87/builtins-x87.cc b/src/x87/builtins-x87.cc
index d6311752..51bb3a7c 100644
--- a/src/x87/builtins-x87.cc
+++ b/src/x87/builtins-x87.cc
@@ -160,18 +160,17 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (!is_api_function) {
Label allocate;
// The code below relies on these assumptions.
- STATIC_ASSERT(JSFunction::kNoSlackTracking == 0);
- STATIC_ASSERT(Map::ConstructionCount::kShift +
- Map::ConstructionCount::kSize == 32);
+ STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
// Check if slack tracking is enabled.
__ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
- __ shr(esi, Map::ConstructionCount::kShift);
- __ j(zero, &allocate); // JSFunction::kNoSlackTracking
+ __ shr(esi, Map::Counter::kShift);
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
+ __ j(less, &allocate);
// Decrease generous allocation count.
__ sub(FieldOperand(eax, Map::kBitField3Offset),
- Immediate(1 << Map::ConstructionCount::kShift));
+ Immediate(1 << Map::Counter::kShift));
- __ cmp(esi, JSFunction::kFinishSlackTracking);
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
__ j(not_equal, &allocate);
__ push(eax);
@@ -182,7 +181,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ pop(edi);
__ pop(eax);
- __ xor_(esi, esi); // JSFunction::kNoSlackTracking
+ __ mov(esi, Map::kSlackTrackingCounterEnd - 1);
__ bind(&allocate);
}
@@ -219,8 +218,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Label no_inobject_slack_tracking;
// Check if slack tracking is enabled.
- __ cmp(esi, JSFunction::kNoSlackTracking);
- __ j(equal, &no_inobject_slack_tracking);
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
+ __ j(less, &no_inobject_slack_tracking);
// Allocate object with a slack.
__ movzx_b(esi,
@@ -1002,17 +1001,21 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ bind(&loop);
__ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments
- // Use inline caching to speed up access to arguments.
if (FLAG_vector_ics) {
- __ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(0)));
+ // TODO(mvstanton): Vector-based ics need additional infrastructure to
+ // be embedded here. For now, just call the runtime.
+ __ push(receiver);
+ __ push(key);
+ __ CallRuntime(Runtime::kGetProperty, 2);
+ } else {
+ // Use inline caching to speed up access to arguments.
+ Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
+ __ call(ic, RelocInfo::CODE_TARGET);
+ // It is important that we do not have a test instruction after the
+ // call. A test instruction after the call is used to indicate that
+ // we have generated an inline version of the keyed load. In this
+ // case, we know that we are not generating a test instruction next.
}
- Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
- __ call(ic, RelocInfo::CODE_TARGET);
- // It is important that we do not have a test instruction after the
- // call. A test instruction after the call is used to indicate that
- // we have generated an inline version of the keyed load. In this
- // case, we know that we are not generating a test instruction next.
// Push the nth argument.
__ push(eax);
diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc
index d4c383be..1264dd9b 100644
--- a/src/x87/code-stubs-x87.cc
+++ b/src/x87/code-stubs-x87.cc
@@ -15,7 +15,7 @@
#include "src/isolate.h"
#include "src/jsregexp.h"
#include "src/regexp-macro-assembler.h"
-#include "src/runtime.h"
+#include "src/runtime/runtime.h"
namespace v8 {
namespace internal {
@@ -333,8 +333,19 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
- NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax,
- ebx, &miss);
+ if (FLAG_vector_ics) {
+ // With careful management, we won't have to save slot and vector on
+ // the stack. Simply handle the possibly missing case first.
+ // TODO(mvstanton): this code can be more efficient.
+ __ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset),
+ Immediate(isolate()->factory()->the_hole_value()));
+ __ j(equal, &miss);
+ __ TryGetFunctionPrototype(receiver, eax, ebx, &miss);
+ __ ret(0);
+ } else {
+ NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax,
+ ebx, &miss);
+ }
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
@@ -371,6 +382,42 @@ void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
}
+void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
+ // Return address is on the stack.
+ Label miss;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register index = LoadDescriptor::NameRegister();
+ Register scratch = edi;
+ DCHECK(!scratch.is(receiver) && !scratch.is(index));
+ Register result = eax;
+ DCHECK(!result.is(scratch));
+ DCHECK(!FLAG_vector_ics ||
+ (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
+ result.is(VectorLoadICDescriptor::SlotRegister())));
+
+ // StringCharAtGenerator doesn't use the result register until it's passed
+ // the different miss possibilities. If it did, we would have a conflict
+ // when FLAG_vector_ics is true.
+
+ StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
+ &miss, // When not a string.
+ &miss, // When not a number.
+ &miss, // When index out of range.
+ STRING_INDEX_IS_ARRAY_INDEX,
+ RECEIVER_IS_STRING);
+ char_at_generator.GenerateFast(masm);
+ __ ret(0);
+
+ StubRuntimeCallHelper call_helper;
+ char_at_generator.GenerateSlow(masm, call_helper);
+
+ __ bind(&miss);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in edx and the parameter count is in eax.
DCHECK(edx.is(ArgumentsAccessReadDescriptor::index()));
@@ -1871,6 +1918,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
// edi - function
// edx - slot id
Isolate* isolate = masm->isolate();
+ const int with_types_offset =
+ FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
+ const int generic_offset =
+ FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
Label extra_checks_or_miss, slow_start;
Label slow, non_function, wrap, cont;
Label have_js_function;
@@ -1910,28 +1961,66 @@ void CallICStub::Generate(MacroAssembler* masm) {
}
__ bind(&extra_checks_or_miss);
- Label miss;
+ Label uninitialized, miss;
__ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
FixedArray::kHeaderSize));
__ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
__ j(equal, &slow_start);
+
+ // The following cases attempt to handle MISS cases without going to the
+ // runtime.
+ if (FLAG_trace_ic) {
+ __ jmp(&miss);
+ }
+
__ cmp(ecx, Immediate(TypeFeedbackVector::UninitializedSentinel(isolate)));
+ __ j(equal, &uninitialized);
+
+ // We are going megamorphic. If the feedback is a JSFunction, it is fine
+ // to handle it here. More complex cases are dealt with in the runtime.
+ __ AssertNotSmi(ecx);
+ __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
+ __ j(not_equal, &miss);
+ __ mov(
+ FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
+ Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
+ // We have to update statistics for runtime profiling.
+ __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
+ __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1)));
+ __ jmp(&slow_start);
+
+ __ bind(&uninitialized);
+
+ // We are going monomorphic, provided we actually have a JSFunction.
+ __ JumpIfSmi(edi, &miss);
+
+ // Goto miss case if we do not have a function.
+ __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
+ __ j(not_equal, &miss);
+
+ // Make sure the function is not the Array() function, which requires special
+ // behavior on MISS.
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
+ __ cmp(edi, ecx);
__ j(equal, &miss);
- if (!FLAG_trace_ic) {
- // We are going megamorphic. If the feedback is a JSFunction, it is fine
- // to handle it here. More complex cases are dealt with in the runtime.
- __ AssertNotSmi(ecx);
- __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx);
- __ j(not_equal, &miss);
- __ mov(FieldOperand(ebx, edx, times_half_pointer_size,
- FixedArray::kHeaderSize),
- Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
- __ jmp(&slow_start);
- }
+ // Update stats.
+ __ add(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
+
+ // Store the function.
+ __ mov(
+ FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
+ edi);
- // We are here because tracing is on or we are going monomorphic.
+ // Update the write barrier.
+ __ mov(eax, edi);
+ __ RecordWriteArray(ebx, eax, edx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ __ jmp(&have_js_function);
+
+ // We are here because tracing is on or we encountered a MISS case we can't
+ // handle here.
__ bind(&miss);
GenerateMiss(masm);
@@ -2437,18 +2526,18 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
// If the receiver is a smi trigger the non-string case.
- STATIC_ASSERT(kSmiTag == 0);
- __ JumpIfSmi(object_, receiver_not_string_);
-
- // Fetch the instance type of the receiver into result register.
- __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
- __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
- // If the receiver is not a string trigger the non-string case.
- __ test(result_, Immediate(kIsNotStringMask));
- __ j(not_zero, receiver_not_string_);
+ if (check_mode_ == RECEIVER_IS_UNKNOWN) {
+ __ JumpIfSmi(object_, receiver_not_string_);
+
+ // Fetch the instance type of the receiver into result register.
+ __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset));
+ __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset));
+ // If the receiver is not a string trigger the non-string case.
+ __ test(result_, Immediate(kIsNotStringMask));
+ __ j(not_zero, receiver_not_string_);
+ }
// If the index is non-smi trigger the non-smi case.
- STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(index_, &index_not_smi_);
__ bind(&got_smi_index_);
@@ -2817,14 +2906,61 @@ void SubStringStub::Generate(MacroAssembler* masm) {
// ebx: instance type
// ecx: sub string length (smi)
// edx: from index (smi)
- StringCharAtGenerator generator(
- eax, edx, ecx, eax, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
+ StringCharAtGenerator generator(eax, edx, ecx, eax, &runtime, &runtime,
+ &runtime, STRING_INDEX_IS_NUMBER,
+ RECEIVER_IS_STRING);
generator.GenerateFast(masm);
__ ret(3 * kPointerSize);
generator.SkipSlow(masm, &runtime);
}
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in eax.
+ Label not_smi;
+ __ JumpIfNotSmi(eax, &not_smi, Label::kNear);
+ __ Ret();
+ __ bind(&not_smi);
+
+ Label not_heap_number;
+ __ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
+ __ j(not_equal, &not_heap_number, Label::kNear);
+ __ Ret();
+ __ bind(&not_heap_number);
+
+ Label not_string, slow_string;
+ __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edi);
+ // eax: object
+ // edi: object map
+ __ j(above_equal, &not_string, Label::kNear);
+ // Check if string has a cached array index.
+ __ test(FieldOperand(eax, String::kHashFieldOffset),
+ Immediate(String::kContainsCachedArrayIndexMask));
+ __ j(not_zero, &slow_string, Label::kNear);
+ __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
+ __ IndexFromHash(eax, eax);
+ __ Ret();
+ __ bind(&slow_string);
+ __ pop(ecx); // Pop return address.
+ __ push(eax); // Push argument.
+ __ push(ecx); // Push return address.
+ __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
+ __ bind(&not_string);
+
+ Label not_oddball;
+ __ CmpInstanceType(edi, ODDBALL_TYPE);
+ __ j(not_equal, &not_oddball, Label::kNear);
+ __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset));
+ __ Ret();
+ __ bind(&not_oddball);
+
+ __ pop(ecx); // Pop return address.
+ __ push(eax); // Push argument.
+ __ push(ecx); // Push return address.
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,
diff --git a/src/x87/code-stubs-x87.h b/src/x87/code-stubs-x87.h
index 03ff477f..a079b6f3 100644
--- a/src/x87/code-stubs-x87.h
+++ b/src/x87/code-stubs-x87.h
@@ -76,7 +76,7 @@ class NameDictionaryLookupStub: public PlatformCodeStub {
Register r0,
Register r1);
- virtual bool SometimesSetsUpAFrame() { return false; }
+ bool SometimesSetsUpAFrame() OVERRIDE { return false; }
private:
static const int kInlinedProbes = 4;
@@ -139,7 +139,7 @@ class RecordWriteStub: public PlatformCodeStub {
INCREMENTAL_COMPACTION
};
- virtual bool SometimesSetsUpAFrame() { return false; }
+ bool SometimesSetsUpAFrame() OVERRIDE { return false; }
static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8.
static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8.
@@ -328,9 +328,9 @@ class RecordWriteStub: public PlatformCodeStub {
kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
};
- virtual inline Major MajorKey() const FINAL OVERRIDE { return RecordWrite; }
+ inline Major MajorKey() const FINAL { return RecordWrite; }
- virtual void Generate(MacroAssembler* masm) OVERRIDE;
+ void Generate(MacroAssembler* masm) OVERRIDE;
void GenerateIncremental(MacroAssembler* masm, Mode mode);
void CheckNeedsToInformIncrementalMarker(
MacroAssembler* masm,
@@ -338,7 +338,7 @@ class RecordWriteStub: public PlatformCodeStub {
Mode mode);
void InformIncrementalMarker(MacroAssembler* masm);
- void Activate(Code* code) {
+ void Activate(Code* code) OVERRIDE {
code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
}
diff --git a/src/x87/codegen-x87.cc b/src/x87/codegen-x87.cc
index e33959e6..1321461a 100644
--- a/src/x87/codegen-x87.cc
+++ b/src/x87/codegen-x87.cc
@@ -380,6 +380,19 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
__ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+ // Allocating heap numbers in the loop below can fail and cause a jump to
+ // gc_required. We can't leave a partly initialized FixedArray behind,
+ // so pessimistically fill it with holes now.
+ Label initialization_loop, initialization_loop_entry;
+ __ jmp(&initialization_loop_entry, Label::kNear);
+ __ bind(&initialization_loop);
+ __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
+ masm->isolate()->factory()->the_hole_value());
+ __ bind(&initialization_loop_entry);
+ __ sub(ebx, Immediate(Smi::FromInt(1)));
+ __ j(not_sign, &initialization_loop);
+
+ __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
__ jmp(&entry);
// ebx: target map
diff --git a/src/x87/debug-x87.cc b/src/x87/debug-x87.cc
index 92c23abe..cdbcbad9 100644
--- a/src/x87/debug-x87.cc
+++ b/src/x87/debug-x87.cc
@@ -182,7 +182,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-x87.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
- Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
+ RegList regs = receiver.bit() | name.bit();
+ if (FLAG_vector_ics) {
+ regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
+ }
+ Generate_DebugBreakCallHelper(masm, regs, 0, false);
}
diff --git a/src/x87/deoptimizer-x87.cc b/src/x87/deoptimizer-x87.cc
index a76c7a70..0e53a0e8 100644
--- a/src/x87/deoptimizer-x87.cc
+++ b/src/x87/deoptimizer-x87.cc
@@ -27,7 +27,7 @@ void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
HandleScope scope(isolate);
// Compute the size of relocation information needed for the code
- // patching in Deoptimizer::DeoptimizeFunction.
+ // patching in Deoptimizer::PatchCodeForDeoptimization below.
int min_reloc_size = 0;
int prev_pc_offset = 0;
DeoptimizationInputData* deopt_data =
diff --git a/src/x87/disasm-x87.cc b/src/x87/disasm-x87.cc
index 908e8b04..8c77d771 100644
--- a/src/x87/disasm-x87.cc
+++ b/src/x87/disasm-x87.cc
@@ -1698,17 +1698,17 @@ int DisassemblerX87::InstructionDecode(v8::internal::Vector<char> out_buffer,
//------------------------------------------------------------------------------
-static const char* cpu_regs[8] = {
+static const char* const cpu_regs[8] = {
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
};
-static const char* byte_cpu_regs[8] = {
+static const char* const byte_cpu_regs[8] = {
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"
};
-static const char* xmm_regs[8] = {
+static const char* const xmm_regs[8] = {
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
};
diff --git a/src/x87/full-codegen-x87.cc b/src/x87/full-codegen-x87.cc
index c159edde..0f292cc4 100644
--- a/src/x87/full-codegen-x87.cc
+++ b/src/x87/full-codegen-x87.cc
@@ -188,10 +188,10 @@ void FullCodeGenerator::Generate() {
Comment cmnt(masm_, "[ Allocate context");
bool need_write_barrier = true;
// Argument to NewContext is the function, which is still in edi.
- if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
+ if (FLAG_harmony_scoping && info->scope()->is_script_scope()) {
__ push(edi);
__ Push(info->scope()->GetScopeInfo());
- __ CallRuntime(Runtime::kNewGlobalContext, 2);
+ __ CallRuntime(Runtime::kNewScriptContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(isolate(), heap_slots);
__ CallStub(&stub);
@@ -865,7 +865,7 @@ void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
EmitDebugCheckDeclarationContext(variable);
// Load instance object.
- __ LoadContext(eax, scope_->ContextChainLength(scope_->GlobalScope()));
+ __ LoadContext(eax, scope_->ContextChainLength(scope_->ScriptScope()));
__ mov(eax, ContextOperand(eax, variable->interface()->Index()));
__ mov(eax, ContextOperand(eax, Context::EXTENSION_INDEX));
@@ -1024,7 +1024,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Comment cmnt(masm_, "[ ForInStatement");
- int slot = stmt->ForInFeedbackSlot();
+ FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
SetStatementPosition(stmt);
@@ -1034,6 +1034,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Get the object to enumerate over. If the object is null or undefined, skip
// over the loop. See ECMA-262 version 5, section 12.6.4.
+ SetExpressionPosition(stmt->enumerable());
VisitForAccumulatorValue(stmt->enumerable());
__ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, &exit);
@@ -1051,6 +1052,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(eax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ bind(&done_convert);
+ PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
// Check for proxies.
@@ -1072,6 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ push(eax);
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+ PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->meta_map());
__ j(not_equal, &fixed_array);
@@ -1106,7 +1109,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// No need for a write barrier, we are storing a Smi in the feedback vector.
__ LoadHeapObject(ebx, FeedbackVector());
- __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
+ int vector_index = FeedbackVector()->GetIndex(slot);
+ __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(vector_index)),
Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
@@ -1125,6 +1129,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Generate code for doing the condition check.
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&loop);
+ SetExpressionPosition(stmt->each());
+
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
__ j(above_equal, loop_statement.break_label());
@@ -1191,48 +1197,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
}
-void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
- Comment cmnt(masm_, "[ ForOfStatement");
- SetStatementPosition(stmt);
-
- Iteration loop_statement(this, stmt);
- increment_loop_depth();
-
- // var iterator = iterable[Symbol.iterator]();
- VisitForEffect(stmt->assign_iterator());
-
- // Loop entry.
- __ bind(loop_statement.continue_label());
-
- // result = iterator.next()
- VisitForEffect(stmt->next_result());
-
- // if (result.done) break;
- Label result_not_done;
- VisitForControl(stmt->result_done(),
- loop_statement.break_label(),
- &result_not_done,
- &result_not_done);
- __ bind(&result_not_done);
-
- // each = result.value
- VisitForEffect(stmt->assign_each());
-
- // Generate code for the body of the loop.
- Visit(stmt->body());
-
- // Check stack before looping.
- PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
- EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
- __ jmp(loop_statement.continue_label());
-
- // Exit and decrement the loop depth.
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
- __ bind(loop_statement.break_label());
- decrement_loop_depth();
-}
-
-
void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
bool pretenure) {
// Use the fast case closure allocation code that allocates in new
@@ -1276,7 +1240,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ mov(LoadDescriptor::NameRegister(), home_object_symbol);
- CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ }
__ cmp(eax, isolate()->factory()->undefined_value());
Label done;
@@ -1286,6 +1256,19 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
}
+void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
+ int offset) {
+ if (NeedsHomeObject(initializer)) {
+ __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
+ __ mov(StoreDescriptor::NameRegister(),
+ Immediate(isolate()->factory()->home_object_symbol()));
+ __ mov(StoreDescriptor::ValueRegister(),
+ Operand(esp, offset * kPointerSize));
+ CallStoreIC();
+ }
+}
+
+
void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state,
Label* slow) {
@@ -1340,7 +1323,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
__ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
@@ -1427,7 +1410,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
__ mov(LoadDescriptor::NameRegister(), var->name());
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
CallLoadIC(CONTEXTUAL);
context()->Plug(eax);
@@ -1611,6 +1594,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
FastCloneShallowObjectStub stub(isolate(), properties_count);
__ CallStub(&stub);
}
+ PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in eax.
@@ -1639,6 +1623,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
// Fall through.
case ObjectLiteral::Property::COMPUTED:
+ // It is safe to use [[Put]] here because the boilerplate already
+ // contains computed properties with an uninitialized value.
if (key->value()->IsInternalizedString()) {
if (property->emit_store()) {
VisitForAccumulatorValue(value);
@@ -1647,6 +1633,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
+
+ if (NeedsHomeObject(value)) {
+ __ mov(StoreDescriptor::ReceiverRegister(), eax);
+ __ mov(StoreDescriptor::NameRegister(),
+ Immediate(isolate()->factory()->home_object_symbol()));
+ __ mov(StoreDescriptor::ValueRegister(), Operand(esp, 0));
+ CallStoreIC();
+ }
} else {
VisitForEffect(value);
}
@@ -1656,6 +1650,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
+ EmitSetHomeObjectIfNeeded(value, 2);
__ push(Immediate(Smi::FromInt(SLOPPY))); // Strict mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
@@ -1666,7 +1661,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(value);
if (property->emit_store()) {
- __ CallRuntime(Runtime::kSetPrototype, 2);
+ __ CallRuntime(Runtime::kInternalSetPrototype, 2);
} else {
__ Drop(2);
}
@@ -1688,7 +1683,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ push(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
+ EmitSetHomeObjectIfNeeded(it->second->getter, 2);
EmitAccessor(it->second->setter);
+ EmitSetHomeObjectIfNeeded(it->second->setter, 3);
__ push(Immediate(Smi::FromInt(NONE)));
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
}
@@ -1801,22 +1798,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
Comment cmnt(masm_, "[ Assignment");
- // Left-hand side can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
- if (property != NULL) {
- assign_type = (property->key()->IsPropertyName())
- ? NAMED_PROPERTY
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
case VARIABLE:
// Nothing to do here.
break;
+ case NAMED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ push(result_register());
+ if (expr->is_compound()) {
+ __ push(MemOperand(esp, kPointerSize));
+ __ push(result_register());
+ }
+ break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
// We need the receiver both on the stack and in the register.
@@ -1826,6 +1824,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
VisitForStackValue(property->obj());
}
break;
+ case KEYED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(property->key());
+ __ Push(result_register());
+ if (expr->is_compound()) {
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(result_register());
+ }
+ break;
case KEYED_PROPERTY: {
if (expr->is_compound()) {
VisitForStackValue(property->obj());
@@ -1850,10 +1860,18 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), TOS_REG);
break;
+ case NAMED_SUPER_PROPERTY:
+ EmitNamedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
@@ -1899,6 +1917,14 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case NAMED_PROPERTY:
EmitNamedPropertyAssignment(expr);
break;
+ case NAMED_SUPER_PROPERTY:
+ EmitNamedSuperPropertyStore(property);
+ context()->Plug(result_register());
+ break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyStore(property);
+ context()->Plug(result_register());
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr);
break;
@@ -2031,7 +2057,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ mov(load_receiver, Operand(esp, kPointerSize));
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
+ Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
}
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
CallIC(ic, TypeFeedbackId::None());
@@ -2051,7 +2077,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
isolate()->factory()->done_string()); // "done"
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(expr->DoneFeedbackSlot())));
+ Immediate(SmiFromSlot(expr->DoneFeedbackSlot())));
}
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
@@ -2065,7 +2091,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
isolate()->factory()->value_string()); // "value"
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(expr->ValueFeedbackSlot())));
+ Immediate(SmiFromSlot(expr->ValueFeedbackSlot())));
}
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
@@ -2086,15 +2112,6 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
VisitForAccumulatorValue(value);
__ pop(ebx);
- // Check generator state.
- Label wrong_state, closed_state, done;
- STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
- STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
- __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset),
- Immediate(Smi::FromInt(0)));
- __ j(equal, &closed_state);
- __ j(less, &wrong_state);
-
// Load suspended function and context.
__ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset));
__ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset));
@@ -2116,7 +2133,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
// Enter a new JavaScript frame, and initialize its slots as they were when
// the generator was suspended.
- Label resume_frame;
+ Label resume_frame, done;
__ bind(&push_frame);
__ call(&resume_frame);
__ jmp(&done);
@@ -2163,25 +2180,6 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
// Not reached: the runtime call returns elsewhere.
__ Abort(kGeneratorFailedToResume);
- // Reach here when generator is closed.
- __ bind(&closed_state);
- if (resume_mode == JSGeneratorObject::NEXT) {
- // Return completed iterator result when generator is closed.
- __ push(Immediate(isolate()->factory()->undefined_value()));
- // Pop value from top-of-stack slot; box result into result register.
- EmitCreateIteratorResult(true);
- } else {
- // Throw the provided value.
- __ push(eax);
- __ CallRuntime(Runtime::kThrow, 1);
- }
- __ jmp(&done);
-
- // Throw error if we attempt to operate on a running generator.
- __ bind(&wrong_state);
- __ push(ebx);
- __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
-
__ bind(&done);
context()->Plug(result_register());
}
@@ -2229,10 +2227,12 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
+ DCHECK(!prop->IsSuperAccess());
+
__ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
@@ -2241,15 +2241,12 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object.
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
DCHECK(prop->IsSuperAccess());
- SuperReference* super_ref = prop->obj()->AsSuperReference();
- EmitLoadHomeObject(super_ref);
- __ push(eax);
- VisitForStackValue(super_ref->this_var());
__ push(Immediate(key->value()));
__ CallRuntime(Runtime::kLoadFromSuper, 3);
}
@@ -2260,7 +2257,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
CallIC(ic);
} else {
CallIC(ic, prop->PropertyFeedbackId());
@@ -2268,6 +2265,14 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
}
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
+
+
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
Token::Value op,
OverwriteMode mode,
@@ -2363,6 +2368,61 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
}
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
+ // Constructor is in eax.
+ DCHECK(lit != NULL);
+ __ push(eax);
+
+ // No access check is needed here since the constructor is created by the
+ // class literal.
+ Register scratch = ebx;
+ __ mov(scratch, FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
+ __ Push(scratch);
+
+ for (int i = 0; i < lit->properties()->length(); i++) {
+ ObjectLiteral::Property* property = lit->properties()->at(i);
+ Literal* key = property->key()->AsLiteral();
+ Expression* value = property->value();
+ DCHECK(key != NULL);
+
+ if (property->is_static()) {
+ __ push(Operand(esp, kPointerSize)); // constructor
+ } else {
+ __ push(Operand(esp, 0)); // prototype
+ }
+ VisitForStackValue(key);
+ VisitForStackValue(value);
+ EmitSetHomeObjectIfNeeded(value, 2);
+
+ switch (property->kind()) {
+ case ObjectLiteral::Property::CONSTANT:
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+ case ObjectLiteral::Property::COMPUTED:
+ case ObjectLiteral::Property::PROTOTYPE:
+ __ CallRuntime(Runtime::kDefineClassMethod, 3);
+ break;
+
+ case ObjectLiteral::Property::GETTER:
+ __ CallRuntime(Runtime::kDefineClassGetter, 3);
+ break;
+
+ case ObjectLiteral::Property::SETTER:
+ __ CallRuntime(Runtime::kDefineClassSetter, 3);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ // prototype
+ __ CallRuntime(Runtime::kToFastProperties, 1);
+
+ // constructor
+ __ CallRuntime(Runtime::kToFastProperties, 1);
+}
+
+
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
Token::Value op,
OverwriteMode mode) {
@@ -2378,16 +2438,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitAssignment(Expression* expr) {
DCHECK(expr->IsValidReferenceExpression());
- // Left-hand side can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->AsProperty();
- if (prop != NULL) {
- assign_type = (prop->key()->IsPropertyName())
- ? NAMED_PROPERTY
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
@@ -2406,6 +2458,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
CallStoreIC();
break;
}
+ case NAMED_SUPER_PROPERTY: {
+ __ push(eax);
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ // stack: value, this; eax: home_object
+ Register scratch = ecx;
+ Register scratch2 = edx;
+ __ mov(scratch, result_register()); // home_object
+ __ mov(eax, MemOperand(esp, kPointerSize)); // value
+ __ mov(scratch2, MemOperand(esp, 0)); // this
+ __ mov(MemOperand(esp, kPointerSize), scratch2); // this
+ __ mov(MemOperand(esp, 0), scratch); // home_object
+ // stack: this, home_object. eax: value
+ EmitNamedSuperPropertyStore(prop);
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ __ push(eax);
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ Register scratch = ecx;
+ Register scratch2 = edx;
+ __ mov(scratch2, MemOperand(esp, 2 * kPointerSize)); // value
+ // stack: value, this, home_object; eax: key, edx: value
+ __ mov(scratch, MemOperand(esp, kPointerSize)); // this
+ __ mov(MemOperand(esp, 2 * kPointerSize), scratch);
+ __ mov(scratch, MemOperand(esp, 0)); // home_object
+ __ mov(MemOperand(esp, kPointerSize), scratch);
+ __ mov(MemOperand(esp, 0), eax);
+ __ mov(eax, scratch2);
+ // stack: this, home_object, key; eax: value.
+ EmitKeyedSuperPropertyStore(prop);
+ break;
+ }
case KEYED_PROPERTY: {
__ push(eax); // Preserve value.
VisitForStackValue(prop->obj());
@@ -2474,7 +2562,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&assign);
EmitStoreToStackLocalOrContextSlot(var, location);
-
} else if (!var->is_const_mode() || op == Token::INIT_CONST) {
if (var->IsLookupSlot()) {
// Assignment to var.
@@ -2496,8 +2583,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
}
EmitStoreToStackLocalOrContextSlot(var, location);
}
+ } else if (IsSignallingAssignmentToConst(var, op, strict_mode())) {
+ __ CallRuntime(Runtime::kThrowConstAssignError, 0);
}
- // Non-initializing assignments to consts are ignored.
}
@@ -2520,6 +2608,34 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
}
+void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // eax : value
+ // stack : receiver ('this'), home_object
+ DCHECK(prop != NULL);
+ Literal* key = prop->key()->AsLiteral();
+ DCHECK(key != NULL);
+
+ __ push(Immediate(key->value()));
+ __ push(eax);
+ __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
+ : Runtime::kStoreToSuper_Sloppy),
+ 4);
+}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // eax : value
+ // stack : receiver ('this'), home_object, key
+
+ __ push(eax);
+ __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
+ : Runtime::kStoreKeyedToSuper_Sloppy),
+ 4);
+}
+
+
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC.
// eax : value
@@ -2549,16 +2665,27 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), result_register());
EmitNamedPropertyLoad(expr);
} else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ push(result_register());
EmitNamedSuperPropertyLoad(expr);
}
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(eax);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ pop(LoadDescriptor::ReceiverRegister()); // Object.
- __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ pop(LoadDescriptor::ReceiverRegister()); // Object.
+ __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(eax);
}
}
@@ -2617,14 +2744,14 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
__ push(eax);
VisitForAccumulatorValue(super_ref->this_var());
__ push(eax);
- __ push(Operand(esp, kPointerSize));
__ push(eax);
+ __ push(Operand(esp, kPointerSize * 2));
__ push(Immediate(key->value()));
// Stack here:
// - home_object
// - this (receiver)
- // - home_object <-- LoadFromSuper will pop here and below.
- // - this (receiver)
+ // - this (receiver) <-- LoadFromSuper will pop here and below.
+ // - home_object
// - key
__ CallRuntime(Runtime::kLoadFromSuper, 3);
@@ -2661,6 +2788,40 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
}
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ // Load the function from the receiver.
+ SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ push(eax);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ push(eax);
+ __ push(eax);
+ __ push(Operand(esp, kPointerSize * 2));
+ VisitForStackValue(prop->key());
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ mov(Operand(esp, kPointerSize), eax);
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
// Load the arguments.
ZoneList<Expression*>* args = expr->arguments();
@@ -2675,7 +2836,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
SetSourcePosition(expr->position());
Handle<Code> ic = CallIC::initialize_stub(
isolate(), arg_count, call_type);
- __ Move(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
+ __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackSlot())));
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
// Don't assign a type feedback id to the IC, since type feedback is provided
// by the vector above.
@@ -2713,6 +2874,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
}
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) {
+ DCHECK(super_ref != NULL);
+ __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
+
+
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
@@ -2748,6 +2916,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// edx (receiver). Touch up the stack with the right values.
__ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
+
+ PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
}
// Record source position for debugger.
SetSourcePosition(expr->position());
@@ -2779,6 +2949,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
__ push(eax); // Function.
__ push(edx); // Receiver.
+ PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the function
// and receiver and have the slow path jump around this code.
@@ -2801,9 +2972,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
@@ -2815,6 +2989,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ EmitLoadSuperConstructor(super_ref);
+ __ push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
@@ -2842,7 +3022,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
@@ -2862,12 +3047,12 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Record call targets in unoptimized code.
if (FLAG_pretenuring_call_new) {
EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
- DCHECK(expr->AllocationSiteFeedbackSlot() ==
- expr->CallNewFeedbackSlot() + 1);
+ DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() ==
+ expr->CallNewFeedbackSlot().ToInt() + 1);
}
__ LoadHeapObject(ebx, FeedbackVector());
- __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
+ __ mov(edx, Immediate(SmiFromSlot(expr->CallNewFeedbackSlot())));
CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
@@ -3181,6 +3366,31 @@ void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
}
+void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK(args->length() == 1);
+
+ VisitForAccumulatorValue(args->at(0));
+
+ Label materialize_true, materialize_false;
+ Label* if_true = NULL;
+ Label* if_false = NULL;
+ Label* fall_through = NULL;
+ context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+ &if_false, &fall_through);
+
+ __ JumpIfSmi(eax, if_false);
+ Register map = ebx;
+ __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
+ __ CmpInstanceType(map, FIRST_JS_PROXY_TYPE);
+ __ j(less, if_false);
+ __ CmpInstanceType(map, LAST_JS_PROXY_TYPE);
+ PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+ Split(less_equal, if_true, if_false, fall_through);
+
+ context()->Plug(if_true, if_false);
+}
+
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
DCHECK(expr->arguments()->length() == 0);
@@ -4118,7 +4328,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
__ mov(LoadDescriptor::NameRegister(), Immediate(expr->name()));
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
+ Immediate(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
@@ -4279,17 +4489,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
- // Expression can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
- // In case of a property we use the uninitialized expression context
- // of the key to detect a named property.
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
@@ -4301,18 +4502,50 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
if (expr->is_postfix() && !context()->IsEffect()) {
__ push(Immediate(Smi::FromInt(0)));
}
- if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the register.
- VisitForStackValue(prop->obj());
- __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
- EmitNamedPropertyLoad(prop);
- } else {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
- __ mov(LoadDescriptor::ReceiverRegister(),
- Operand(esp, kPointerSize)); // Object.
- __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
- EmitKeyedPropertyLoad(prop);
+ switch (assign_type) {
+ case NAMED_PROPERTY: {
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
+ EmitNamedPropertyLoad(prop);
+ break;
+ }
+
+ case NAMED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ push(result_register());
+ __ push(MemOperand(esp, kPointerSize));
+ __ push(result_register());
+ EmitNamedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ __ push(result_register());
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(MemOperand(esp, 2 * kPointerSize));
+ __ push(result_register());
+ EmitKeyedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_PROPERTY: {
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
+ __ mov(LoadDescriptor::ReceiverRegister(),
+ Operand(esp, kPointerSize)); // Object.
+ __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
+ EmitKeyedPropertyLoad(prop);
+ break;
+ }
+
+ case VARIABLE:
+ UNREACHABLE();
}
}
@@ -4344,9 +4577,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax);
break;
+ case NAMED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 2 * kPointerSize), eax);
+ break;
case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 3 * kPointerSize), eax);
+ break;
}
}
}
@@ -4382,9 +4621,15 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax);
break;
+ case NAMED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 2 * kPointerSize), eax);
+ break;
case KEYED_PROPERTY:
__ mov(Operand(esp, 2 * kPointerSize), eax);
break;
+ case KEYED_SUPER_PROPERTY:
+ __ mov(Operand(esp, 3 * kPointerSize), eax);
+ break;
}
}
}
@@ -4441,6 +4686,28 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
break;
}
+ case NAMED_SUPER_PROPERTY: {
+ EmitNamedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
+ } else {
+ context()->Plug(eax);
+ }
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ EmitKeyedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
+ } else {
+ context()->Plug(eax);
+ }
+ break;
+ }
case KEYED_PROPERTY: {
__ pop(StoreDescriptor::NameRegister());
__ pop(StoreDescriptor::ReceiverRegister());
@@ -4473,7 +4740,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
__ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
// Use a regular load, not a contextual load, to avoid a reference
// error.
@@ -4708,7 +4975,7 @@ void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
Scope* declaration_scope = scope()->DeclarationScope();
- if (declaration_scope->is_global_scope() ||
+ if (declaration_scope->is_script_scope() ||
declaration_scope->is_module_scope()) {
// Contexts nested in the native context have a canonical empty function
// as their closure, not the anonymous closure containing the global
diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc
index 8dfad363..26ce4dcb 100644
--- a/src/x87/interface-descriptors-x87.cc
+++ b/src/x87/interface-descriptors-x87.cc
@@ -29,6 +29,9 @@ const Register StoreDescriptor::NameRegister() { return ecx; }
const Register StoreDescriptor::ValueRegister() { return eax; }
+const Register StoreTransitionDescriptor::MapRegister() { return ebx; }
+
+
const Register ElementTransitionAndStoreDescriptor::MapRegister() {
return ebx;
}
@@ -152,6 +155,15 @@ void TransitionElementsKindDescriptor::Initialize(
}
+void AllocateHeapNumberDescriptor::Initialize(
+ CallInterfaceDescriptorData* data) {
+ // register state
+ // esi -- context
+ Register registers[] = {esi};
+ data->Initialize(arraysize(registers), registers, nullptr);
+}
+
+
void ArrayConstructorConstantArgCountDescriptor::Initialize(
CallInterfaceDescriptorData* data) {
// register state
diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc
index a5bc5eae..c292bb94 100644
--- a/src/x87/lithium-codegen-x87.cc
+++ b/src/x87/lithium-codegen-x87.cc
@@ -32,9 +32,9 @@ class SafepointGenerator FINAL : public CallWrapper {
deopt_mode_(mode) {}
virtual ~SafepointGenerator() {}
- virtual void BeforeCall(int call_size) const OVERRIDE {}
+ void BeforeCall(int call_size) const OVERRIDE {}
- virtual void AfterCall() const OVERRIDE {
+ void AfterCall() const OVERRIDE {
codegen_->RecordSafepoint(pointers_, deopt_mode_);
}
@@ -2924,10 +2924,10 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
Label* map_check() { return &map_check_; }
private:
LInstanceOfKnownGlobal* instr_;
@@ -3050,6 +3050,7 @@ void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
}
__ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
} else {
+ DCHECK(info()->IsStub()); // Functions would need to drop one more value.
Register reg = ToRegister(instr->parameter_count());
// The argument count parameter is a smi
__ SmiUntag(reg);
@@ -3124,13 +3125,18 @@ void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
template <class T>
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
DCHECK(FLAG_vector_ics);
- Register vector = ToRegister(instr->temp_vector());
- DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
- __ mov(vector, instr->hydrogen()->feedback_vector());
+ Register vector_register = ToRegister(instr->temp_vector());
+ Register slot_register = VectorLoadICDescriptor::SlotRegister();
+ DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
+ DCHECK(slot_register.is(eax));
+
+ AllowDeferredHandleDereference vector_structure_check;
+ Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
+ __ mov(vector_register, vector);
// No need to allocate this register.
- DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax));
- __ mov(VectorLoadICDescriptor::SlotRegister(),
- Immediate(Smi::FromInt(instr->hydrogen()->slot())));
+ FeedbackVectorICSlot slot = instr->hydrogen()->slot();
+ int index = vector->GetIndex(slot);
+ __ mov(slot_register, Immediate(Smi::FromInt(index)));
}
@@ -3145,7 +3151,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
}
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
- Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
+ Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -3275,7 +3281,8 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
if (FLAG_vector_ics) {
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
}
- Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
+ Handle<Code> ic =
+ CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -3498,7 +3505,7 @@ void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
}
- Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+ Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -3734,45 +3741,81 @@ void LCodeGen::DoTailCallThroughMegamorphicCache(
Register name = ToRegister(instr->name());
DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
DCHECK(name.is(LoadDescriptor::NameRegister()));
+ Register slot = FLAG_vector_ics ? ToRegister(instr->slot()) : no_reg;
+ Register vector = FLAG_vector_ics ? ToRegister(instr->vector()) : no_reg;
Register scratch = ebx;
- Register extra = eax;
+ Register extra = edi;
+ DCHECK(!extra.is(slot) && !extra.is(vector));
DCHECK(!scratch.is(receiver) && !scratch.is(name));
DCHECK(!extra.is(receiver) && !extra.is(name));
// Important for the tail-call.
bool must_teardown_frame = NeedsEagerFrame();
- // The probe will tail call to a handler if found.
- isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
- must_teardown_frame, receiver, name,
- scratch, extra);
+ if (!instr->hydrogen()->is_just_miss()) {
+ if (FLAG_vector_ics) {
+ __ push(slot);
+ __ push(vector);
+ }
+
+ // The probe will tail call to a handler if found.
+ // If --vector-ics is on, then it knows to pop the two args first.
+ DCHECK(!instr->hydrogen()->is_keyed_load());
+ isolate()->stub_cache()->GenerateProbe(
+ masm(), Code::LOAD_IC, instr->hydrogen()->flags(), must_teardown_frame,
+ receiver, name, scratch, extra);
+
+ if (FLAG_vector_ics) {
+ __ pop(vector);
+ __ pop(slot);
+ }
+ }
// Tail call to miss if we ended up here.
if (must_teardown_frame) __ leave();
- LoadIC::GenerateMiss(masm());
+ if (instr->hydrogen()->is_keyed_load()) {
+ KeyedLoadIC::GenerateMiss(masm());
+ } else {
+ LoadIC::GenerateMiss(masm());
+ }
}
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(ToRegister(instr->result()).is(eax));
- LPointerMap* pointers = instr->pointer_map();
- SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
+ if (instr->hydrogen()->IsTailCall()) {
+ if (NeedsEagerFrame()) __ leave();
- if (instr->target()->IsConstantOperand()) {
- LConstantOperand* target = LConstantOperand::cast(instr->target());
- Handle<Code> code = Handle<Code>::cast(ToHandle(target));
- generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
- __ call(code, RelocInfo::CODE_TARGET);
+ if (instr->target()->IsConstantOperand()) {
+ LConstantOperand* target = LConstantOperand::cast(instr->target());
+ Handle<Code> code = Handle<Code>::cast(ToHandle(target));
+ __ jmp(code, RelocInfo::CODE_TARGET);
+ } else {
+ DCHECK(instr->target()->IsRegister());
+ Register target = ToRegister(instr->target());
+ __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
+ __ jmp(target);
+ }
} else {
- DCHECK(instr->target()->IsRegister());
- Register target = ToRegister(instr->target());
- generator.BeforeCall(__ CallSize(Operand(target)));
- __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
- __ call(target);
+ LPointerMap* pointers = instr->pointer_map();
+ SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
+
+ if (instr->target()->IsConstantOperand()) {
+ LConstantOperand* target = LConstantOperand::cast(instr->target());
+ Handle<Code> code = Handle<Code>::cast(ToHandle(target));
+ generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
+ __ call(code, RelocInfo::CODE_TARGET);
+ } else {
+ DCHECK(instr->target()->IsRegister());
+ Register target = ToRegister(instr->target());
+ generator.BeforeCall(__ CallSize(Operand(target)));
+ __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
+ __ call(target);
+ }
+ generator.AfterCall();
}
- generator.AfterCall();
}
@@ -3869,10 +3912,11 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
LMathAbs* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LMathAbs* instr_;
};
@@ -4777,10 +4821,9 @@ void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
LStringCharCodeAt* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
- codegen()->DoDeferredStringCharCodeAt(instr_);
- }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ void Generate() OVERRIDE { codegen()->DoDeferredStringCharCodeAt(instr_); }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LStringCharCodeAt* instr_;
};
@@ -4836,10 +4879,11 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
LStringCharFromCode* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredStringCharFromCode(instr_);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LStringCharFromCode* instr_;
};
@@ -4925,11 +4969,12 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
LNumberTagI* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
SIGNED_INT32);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LNumberTagI* instr_;
};
@@ -4953,11 +4998,12 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
LNumberTagU* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
UNSIGNED_INT32);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LNumberTagU* instr_;
};
@@ -5042,10 +5088,9 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
LNumberTagD* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
- codegen()->DoDeferredNumberTagD(instr_);
- }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ void Generate() OVERRIDE { codegen()->DoDeferredNumberTagD(instr_); }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LNumberTagD* instr_;
};
@@ -5288,10 +5333,9 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
LTaggedToI* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
- codegen()->DoDeferredTaggedToI(instr_, done());
- }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ void Generate() OVERRIDE { codegen()->DoDeferredTaggedToI(instr_, done()); }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LTaggedToI* instr_;
};
@@ -5353,9 +5397,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
Label lost_precision, is_nan, minus_zero, done;
X87Register input_reg = ToX87Register(input);
X87Fxch(input_reg);
- Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
__ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
- &lost_precision, &is_nan, &minus_zero, dist);
+ &lost_precision, &is_nan, &minus_zero);
__ jmp(&done);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
@@ -5378,9 +5421,8 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
Label lost_precision, is_nan, minus_zero, done;
X87Register input_reg = ToX87Register(input);
X87Fxch(input_reg);
- Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
__ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
- &lost_precision, &is_nan, &minus_zero, dist);
+ &lost_precision, &is_nan, &minus_zero);
__ jmp(&done);
__ bind(&lost_precision);
DeoptimizeIf(no_condition, instr, "lost precision");
@@ -5494,11 +5536,12 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
: LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
SetExit(check_maps());
}
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredInstanceMigration(instr_, object_);
}
Label* check_maps() { return &check_maps_; }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LCheckMaps* instr_;
Label check_maps_;
@@ -5717,10 +5760,9 @@ void LCodeGen::DoAllocate(LAllocate* instr) {
LAllocate* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
- codegen()->DoDeferredAllocate(instr_);
- }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ void Generate() OVERRIDE { codegen()->DoDeferredAllocate(instr_); }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LAllocate* instr_;
};
@@ -6086,10 +6128,9 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr,
const X87Stack& x87_stack)
: LDeferredCode(codegen, x87_stack), instr_(instr) { }
- virtual void Generate() OVERRIDE {
- codegen()->DoDeferredStackCheck(instr_);
- }
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ void Generate() OVERRIDE { codegen()->DoDeferredStackCheck(instr_); }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LStackCheck* instr_;
};
@@ -6237,10 +6278,11 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
object_(object),
index_(index) {
}
- virtual void Generate() OVERRIDE {
+ void Generate() OVERRIDE {
codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
}
- virtual LInstruction* instr() OVERRIDE { return instr_; }
+ LInstruction* instr() OVERRIDE { return instr_; }
+
private:
LLoadFieldByIndex* instr_;
Register object_;
diff --git a/src/x87/lithium-x87.cc b/src/x87/lithium-x87.cc
index 9304b897..3a52dc4b 100644
--- a/src/x87/lithium-x87.cc
+++ b/src/x87/lithium-x87.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <sstream>
+
#include "src/v8.h"
#if V8_TARGET_ARCH_X87
@@ -376,9 +378,9 @@ LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
- OStringStream os;
+ std::ostringstream os;
os << hydrogen()->access() << " <- ";
- stream->Add(os.c_str());
+ stream->Add(os.str().c_str());
value()->PrintTo(stream);
}
@@ -736,11 +738,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
// Shift operations can only deoptimize if we do a logical shift by 0 and
// the result cannot be truncated to int32.
if (op == Token::SHR && constant_value == 0) {
- if (FLAG_opt_safe_uint32_operations) {
- does_deopt = !instr->CheckFlag(HInstruction::kUint32);
- } else {
- does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
- }
+ does_deopt = !instr->CheckFlag(HInstruction::kUint32);
}
LInstruction* result =
@@ -1159,9 +1157,17 @@ LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
LOperand* name_register =
UseFixed(instr->name(), LoadDescriptor::NameRegister());
+ LOperand* slot = NULL;
+ LOperand* vector = NULL;
+ if (FLAG_vector_ics) {
+ slot = UseFixed(instr->slot(), VectorLoadICDescriptor::SlotRegister());
+ vector =
+ UseFixed(instr->vector(), VectorLoadICDescriptor::VectorRegister());
+ }
+
// Not marked as call. It can't deoptimize, and it never returns.
return new (zone()) LTailCallThroughMegamorphicCache(
- context, receiver_register, name_register);
+ context, receiver_register, name_register, slot, vector);
}
@@ -2115,7 +2121,7 @@ LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* global_object =
UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
LOperand* vector = NULL;
- if (FLAG_vector_ics) {
+ if (instr->HasVectorAndSlot()) {
vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
@@ -2176,7 +2182,7 @@ LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* object =
UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
LOperand* vector = NULL;
- if (FLAG_vector_ics) {
+ if (instr->HasVectorAndSlot()) {
vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
@@ -2241,7 +2247,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
LOperand* vector = NULL;
- if (FLAG_vector_ics) {
+ if (instr->HasVectorAndSlot()) {
vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
LLoadKeyedGeneric* result =
diff --git a/src/x87/lithium-x87.h b/src/x87/lithium-x87.h
index dbb18eca..5d27fcb7 100644
--- a/src/x87/lithium-x87.h
+++ b/src/x87/lithium-x87.h
@@ -168,17 +168,13 @@ class LCodeGen;
V(WrapReceiver)
-#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
- virtual Opcode opcode() const FINAL OVERRIDE { \
- return LInstruction::k##type; \
- } \
- virtual void CompileToNative(LCodeGen* generator) FINAL OVERRIDE; \
- virtual const char* Mnemonic() const FINAL OVERRIDE { \
- return mnemonic; \
- } \
- static L##type* cast(LInstruction* instr) { \
- DCHECK(instr->Is##type()); \
- return reinterpret_cast<L##type*>(instr); \
+#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
+ Opcode opcode() const FINAL { return LInstruction::k##type; } \
+ void CompileToNative(LCodeGen* generator) FINAL; \
+ const char* Mnemonic() const FINAL { return mnemonic; } \
+ static L##type* cast(LInstruction* instr) { \
+ DCHECK(instr->Is##type()); \
+ return reinterpret_cast<L##type*>(instr); \
}
@@ -297,11 +293,9 @@ class LTemplateResultInstruction : public LInstruction {
public:
// Allow 0 or 1 output operands.
STATIC_ASSERT(R == 0 || R == 1);
- virtual bool HasResult() const FINAL OVERRIDE {
- return R != 0 && result() != NULL;
- }
+ bool HasResult() const FINAL { return R != 0 && result() != NULL; }
void set_result(LOperand* operand) { results_[0] = operand; }
- LOperand* result() const { return results_[0]; }
+ LOperand* result() const OVERRIDE { return results_[0]; }
protected:
EmbeddedContainer<LOperand*, R> results_;
@@ -319,11 +313,11 @@ class LTemplateInstruction : public LTemplateResultInstruction<R> {
private:
// Iterator support.
- virtual int InputCount() FINAL OVERRIDE { return I; }
- virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
+ int InputCount() FINAL { return I; }
+ LOperand* InputAt(int i) FINAL { return inputs_[i]; }
- virtual int TempCount() FINAL OVERRIDE { return T; }
- virtual LOperand* TempAt(int i) FINAL OVERRIDE { return temps_[i]; }
+ int TempCount() FINAL { return T; }
+ LOperand* TempAt(int i) FINAL { return temps_[i]; }
};
@@ -337,8 +331,8 @@ class LGap : public LTemplateInstruction<0, 0, 0> {
}
// Can't use the DECLARE-macro here because of sub-classes.
- virtual bool IsGap() const FINAL OVERRIDE { return true; }
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ bool IsGap() const FINAL { return true; }
+ void PrintDataTo(StringStream* stream) OVERRIDE;
static LGap* cast(LInstruction* instr) {
DCHECK(instr->IsGap());
return reinterpret_cast<LGap*>(instr);
@@ -378,7 +372,7 @@ class LInstructionGap FINAL : public LGap {
public:
explicit LInstructionGap(HBasicBlock* block) : LGap(block) { }
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
return !IsRedundant();
}
@@ -390,9 +384,7 @@ class LClobberDoubles FINAL : public LTemplateInstruction<0, 0, 0> {
public:
explicit LClobberDoubles(Isolate* isolate) { }
- virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
- return true;
- }
+ bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE { return true; }
DECLARE_CONCRETE_INSTRUCTION(ClobberDoubles, "clobber-d")
};
@@ -402,13 +394,13 @@ class LGoto FINAL : public LTemplateInstruction<0, 0, 0> {
public:
explicit LGoto(HBasicBlock* block) : block_(block) { }
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE;
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
- virtual bool IsControl() const OVERRIDE { return true; }
+ void PrintDataTo(StringStream* stream) OVERRIDE;
+ bool IsControl() const OVERRIDE { return true; }
int block_id() const { return block_->block_id(); }
- virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
+ bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
return false;
}
@@ -444,7 +436,7 @@ class LDummyUse FINAL : public LTemplateInstruction<1, 1, 0> {
class LDeoptimize FINAL : public LTemplateInstruction<0, 0, 0> {
public:
- virtual bool IsControl() const OVERRIDE { return true; }
+ bool IsControl() const OVERRIDE { return true; }
DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
DECLARE_HYDROGEN_ACCESSOR(Deoptimize)
};
@@ -455,12 +447,10 @@ class LLabel FINAL : public LGap {
explicit LLabel(HBasicBlock* block)
: LGap(block), replacement_(NULL) { }
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
- return false;
- }
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE { return false; }
DECLARE_CONCRETE_INSTRUCTION(Label, "label")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int block_id() const { return block()->block_id(); }
bool is_loop_header() const { return block()->IsLoopHeader(); }
@@ -478,9 +468,7 @@ class LLabel FINAL : public LGap {
class LParameter FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
- return false;
- }
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE { return false; }
DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
};
@@ -499,19 +487,23 @@ class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
class LTailCallThroughMegamorphicCache FINAL
- : public LTemplateInstruction<0, 3, 0> {
+ : public LTemplateInstruction<0, 5, 0> {
public:
- explicit LTailCallThroughMegamorphicCache(LOperand* context,
- LOperand* receiver,
- LOperand* name) {
+ LTailCallThroughMegamorphicCache(LOperand* context, LOperand* receiver,
+ LOperand* name, LOperand* slot,
+ LOperand* vector) {
inputs_[0] = context;
inputs_[1] = receiver;
inputs_[2] = name;
+ inputs_[3] = slot;
+ inputs_[4] = vector;
}
LOperand* context() { return inputs_[0]; }
LOperand* receiver() { return inputs_[1]; }
LOperand* name() { return inputs_[2]; }
+ LOperand* slot() { return inputs_[3]; }
+ LOperand* vector() { return inputs_[4]; }
DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
"tail-call-through-megamorphic-cache")
@@ -521,9 +513,7 @@ class LTailCallThroughMegamorphicCache FINAL
class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
public:
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
- return false;
- }
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE { return false; }
DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
};
@@ -533,7 +523,7 @@ class LControlInstruction: public LTemplateInstruction<0, I, T> {
public:
LControlInstruction() : false_label_(NULL), true_label_(NULL) { }
- virtual bool IsControl() const FINAL OVERRIDE { return true; }
+ bool IsControl() const FINAL { return true; }
int SuccessorCount() { return hydrogen()->SuccessorCount(); }
HBasicBlock* SuccessorAt(int i) { return hydrogen()->SuccessorAt(i); }
@@ -626,7 +616,7 @@ class LAccessArgumentsAt FINAL : public LTemplateInstruction<1, 3, 0> {
DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -875,7 +865,7 @@ class LCompareNumericAndBranch FINAL : public LControlInstruction<2, 0> {
return hydrogen()->representation().IsDouble();
}
- virtual void PrintDataTo(StringStream* stream);
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1052,7 +1042,7 @@ class LIsObjectAndBranch FINAL : public LControlInstruction<1, 1> {
DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1069,7 +1059,7 @@ class LIsStringAndBranch FINAL : public LControlInstruction<1, 1> {
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1084,7 +1074,7 @@ class LIsSmiAndBranch FINAL : public LControlInstruction<1, 0> {
DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
DECLARE_HYDROGEN_ACCESSOR(IsSmiAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1102,7 +1092,7 @@ class LIsUndetectableAndBranch FINAL : public LControlInstruction<1, 1> {
"is-undetectable-and-branch")
DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1122,7 +1112,7 @@ class LStringCompareAndBranch FINAL : public LControlInstruction<3, 0> {
"string-compare-and-branch")
DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
Token::Value op() const { return hydrogen()->token(); }
};
@@ -1142,7 +1132,7 @@ class LHasInstanceTypeAndBranch FINAL : public LControlInstruction<1, 1> {
"has-instance-type-and-branch")
DECLARE_HYDROGEN_ACCESSOR(HasInstanceTypeAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1171,7 +1161,7 @@ class LHasCachedArrayIndexAndBranch FINAL
DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
"has-cached-array-index-and-branch")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1204,7 +1194,7 @@ class LClassOfTestAndBranch FINAL : public LControlInstruction<1, 2> {
"class-of-test-and-branch")
DECLARE_HYDROGEN_ACCESSOR(ClassOfTestAndBranch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1399,7 +1389,7 @@ class LBranch FINAL : public LControlInstruction<1, 1> {
DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
DECLARE_HYDROGEN_ACCESSOR(Branch)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1552,11 +1542,9 @@ class LArithmeticD FINAL : public LTemplateInstruction<1, 2, 0> {
Token::Value op() const { return op_; }
- virtual Opcode opcode() const OVERRIDE {
- return LInstruction::kArithmeticD;
- }
- virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
- virtual const char* Mnemonic() const OVERRIDE;
+ Opcode opcode() const OVERRIDE { return LInstruction::kArithmeticD; }
+ void CompileToNative(LCodeGen* generator) OVERRIDE;
+ const char* Mnemonic() const OVERRIDE;
private:
Token::Value op_;
@@ -1579,11 +1567,9 @@ class LArithmeticT FINAL : public LTemplateInstruction<1, 3, 0> {
LOperand* left() { return inputs_[1]; }
LOperand* right() { return inputs_[2]; }
- virtual Opcode opcode() const OVERRIDE {
- return LInstruction::kArithmeticT;
- }
- virtual void CompileToNative(LCodeGen* generator) OVERRIDE;
- virtual const char* Mnemonic() const OVERRIDE;
+ Opcode opcode() const OVERRIDE { return LInstruction::kArithmeticT; }
+ void CompileToNative(LCodeGen* generator) OVERRIDE;
+ const char* Mnemonic() const OVERRIDE;
Token::Value op() const { return op_; }
@@ -1696,7 +1682,7 @@ class LLoadKeyed FINAL : public LTemplateInstruction<1, 2, 0> {
DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
uint32_t base_offset() const { return hydrogen()->base_offset(); }
bool key_is_smi() {
return hydrogen()->key()->representation().IsTagged();
@@ -1794,7 +1780,7 @@ class LLoadContextSlot FINAL : public LTemplateInstruction<1, 1, 0> {
int slot_index() { return hydrogen()->slot_index(); }
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1815,7 +1801,7 @@ class LStoreContextSlot FINAL : public LTemplateInstruction<0, 2, 1> {
int slot_index() { return hydrogen()->slot_index(); }
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -1854,7 +1840,7 @@ class LStoreCodeEntry FINAL: public LTemplateInstruction<0, 2, 0> {
LOperand* function() { return inputs_[0]; }
LOperand* code_object() { return inputs_[1]; }
- virtual void PrintDataTo(StringStream* stream);
+ void PrintDataTo(StringStream* stream) OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(StoreCodeEntry, "store-code-entry")
DECLARE_HYDROGEN_ACCESSOR(StoreCodeEntry)
@@ -1871,7 +1857,7 @@ class LInnerAllocatedObject FINAL: public LTemplateInstruction<1, 2, 0> {
LOperand* base_object() const { return inputs_[0]; }
LOperand* offset() const { return inputs_[1]; }
- virtual void PrintDataTo(StringStream* stream);
+ void PrintDataTo(StringStream* stream) OVERRIDE;
DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "inner-allocated-object")
};
@@ -1915,7 +1901,7 @@ class LCallJSFunction FINAL : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
};
@@ -1937,18 +1923,18 @@ class LCallWithDescriptor FINAL : public LTemplateResultInstruction<1> {
private:
DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
ZoneList<LOperand*> inputs_;
// Iterator support.
- virtual int InputCount() FINAL OVERRIDE { return inputs_.length(); }
- virtual LOperand* InputAt(int i) FINAL OVERRIDE { return inputs_[i]; }
+ int InputCount() FINAL { return inputs_.length(); }
+ LOperand* InputAt(int i) FINAL { return inputs_[i]; }
- virtual int TempCount() FINAL OVERRIDE { return 0; }
- virtual LOperand* TempAt(int i) FINAL OVERRIDE { return NULL; }
+ int TempCount() FINAL { return 0; }
+ LOperand* TempAt(int i) FINAL { return NULL; }
};
@@ -1965,7 +1951,7 @@ class LInvokeFunction FINAL : public LTemplateInstruction<1, 2, 0> {
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
};
@@ -2001,7 +1987,7 @@ class LCallNew FINAL : public LTemplateInstruction<1, 2, 0> {
DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
DECLARE_HYDROGEN_ACCESSOR(CallNew)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
};
@@ -2020,7 +2006,7 @@ class LCallNewArray FINAL : public LTemplateInstruction<1, 2, 0> {
DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
};
@@ -2037,7 +2023,7 @@ class LCallRuntime FINAL : public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
- virtual bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
+ bool ClobbersDoubleRegisters(Isolate* isolate) const OVERRIDE {
return save_doubles() == kDontSaveFPRegs;
}
@@ -2225,7 +2211,7 @@ class LStoreNamedField FINAL : public LTemplateInstruction<0, 2, 2> {
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
@@ -2244,7 +2230,7 @@ class LStoreNamedGeneric FINAL : public LTemplateInstruction<0, 3, 0> {
DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2275,7 +2261,7 @@ class LStoreKeyed FINAL : public LTemplateInstruction<0, 3, 0> {
DECLARE_CONCRETE_INSTRUCTION(StoreKeyed, "store-keyed")
DECLARE_HYDROGEN_ACCESSOR(StoreKeyed)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
uint32_t base_offset() const { return hydrogen()->base_offset(); }
bool NeedsCanonicalization() { return hydrogen()->NeedsCanonicalization(); }
};
@@ -2301,7 +2287,7 @@ class LStoreKeyedGeneric FINAL : public LTemplateInstruction<0, 4, 0> {
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedGeneric)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2328,7 +2314,7 @@ class LTransitionElementsKind FINAL : public LTemplateInstruction<0, 2, 2> {
"transition-elements-kind")
DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind)
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
Handle<Map> original_map() { return hydrogen()->original_map().handle(); }
Handle<Map> transitioned_map() {
@@ -2628,15 +2614,13 @@ class LTypeofIsAndBranch FINAL : public LControlInstruction<1, 0> {
Handle<String> type_literal() { return hydrogen()->type_literal(); }
- virtual void PrintDataTo(StringStream* stream) OVERRIDE;
+ void PrintDataTo(StringStream* stream) OVERRIDE;
};
class LOsrEntry FINAL : public LTemplateInstruction<0, 0, 0> {
public:
- virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
- return false;
- }
+ bool HasInterestingComment(LCodeGen* gen) const OVERRIDE { return false; }
DECLARE_CONCRETE_INSTRUCTION(OsrEntry, "osr-entry")
};
@@ -2843,7 +2827,7 @@ class LChunkBuilder FINAL : public LChunkBuilderBase {
// An input operand in register, stack slot or a constant operand.
// Will not be moved to a register even if one is freely available.
- virtual MUST_USE_RESULT LOperand* UseAny(HValue* value) OVERRIDE;
+ MUST_USE_RESULT LOperand* UseAny(HValue* value) OVERRIDE;
// Temporary operand that must be in a register.
MUST_USE_RESULT LUnallocated* TempRegister();
diff --git a/src/x87/macro-assembler-x87.cc b/src/x87/macro-assembler-x87.cc
index a1fa3317..008b2af6 100644
--- a/src/x87/macro-assembler-x87.cc
+++ b/src/x87/macro-assembler-x87.cc
@@ -13,7 +13,7 @@
#include "src/cpu-profiler.h"
#include "src/debug.h"
#include "src/isolate-inl.h"
-#include "src/runtime.h"
+#include "src/runtime/runtime.h"
#include "src/serialize.h"
namespace v8 {
@@ -278,7 +278,7 @@ void MacroAssembler::TruncateHeapNumberToI(Register result_reg,
}
-void MacroAssembler::LoadUint32NoSSE2(Register src) {
+void MacroAssembler::LoadUint32NoSSE2(const Operand& src) {
Label done;
push(src);
fild_s(Operand(esp, 0));
@@ -654,16 +654,16 @@ void MacroAssembler::CheckMap(Register obj,
}
-void MacroAssembler::DispatchMap(Register obj,
- Register unused,
- Handle<Map> map,
- Handle<Code> success,
- SmiCheckType smi_check_type) {
+void MacroAssembler::DispatchWeakMap(Register obj, Register scratch1,
+ Register scratch2, Handle<WeakCell> cell,
+ Handle<Code> success,
+ SmiCheckType smi_check_type) {
Label fail;
if (smi_check_type == DO_SMI_CHECK) {
JumpIfSmi(obj, &fail);
}
- cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map));
+ mov(scratch1, FieldOperand(obj, HeapObject::kMapOffset));
+ CmpWeakValue(scratch1, cell, scratch2);
j(equal, success);
bind(&fail);
@@ -867,6 +867,13 @@ void MacroAssembler::Prologue(bool code_pre_aging) {
}
+void MacroAssembler::EnterFrame(StackFrame::Type type,
+ bool load_constant_pool_pointer_reg) {
+ // Out-of-line constant pool not implemented on x87.
+ UNREACHABLE();
+}
+
+
void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(ebp);
mov(ebp, esp);
@@ -906,8 +913,10 @@ void MacroAssembler::EnterExitFramePrologue() {
// Save the frame pointer and the context in top.
ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
ExternalReference context_address(Isolate::kContextAddress, isolate());
+ ExternalReference c_function_address(Isolate::kCFunctionAddress, isolate());
mov(Operand::StaticVariable(c_entry_fp_address), ebp);
mov(Operand::StaticVariable(context_address), esi);
+ mov(Operand::StaticVariable(c_function_address), ebx);
}
@@ -1312,10 +1321,10 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
}
bind(&done);
- // Check that the value is a normal propety.
+ // Check that the value is a field property.
const int kDetailsOffset =
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
- DCHECK_EQ(NORMAL, 0);
+ DCHECK_EQ(FIELD, 0);
test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
j(not_zero, miss);
@@ -2535,6 +2544,21 @@ void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
}
+void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
+ Register scratch) {
+ mov(scratch, cell);
+ cmp(value, FieldOperand(scratch, WeakCell::kValueOffset));
+}
+
+
+void MacroAssembler::LoadWeakValue(Register value, Handle<WeakCell> cell,
+ Label* miss) {
+ mov(value, cell);
+ mov(value, FieldOperand(value, WeakCell::kValueOffset));
+ JumpIfSmi(value, miss);
+}
+
+
void MacroAssembler::Ret() {
ret(0);
}
@@ -3063,18 +3087,6 @@ void MacroAssembler::CheckPageFlagForMap(
}
-void MacroAssembler::CheckMapDeprecated(Handle<Map> map,
- Register scratch,
- Label* if_deprecated) {
- if (map->CanBeDeprecated()) {
- mov(scratch, map);
- mov(scratch, FieldOperand(scratch, Map::kBitField3Offset));
- and_(scratch, Immediate(Map::Deprecated::kMask));
- j(not_zero, if_deprecated);
- }
-}
-
-
void MacroAssembler::JumpIfBlack(Register object,
Register scratch0,
Register scratch1,
diff --git a/src/x87/macro-assembler-x87.h b/src/x87/macro-assembler-x87.h
index c9e9087f..b7972651 100644
--- a/src/x87/macro-assembler-x87.h
+++ b/src/x87/macro-assembler-x87.h
@@ -93,10 +93,6 @@ class MacroAssembler: public Assembler {
Label* condition_met,
Label::Distance condition_met_distance = Label::kFar);
- void CheckMapDeprecated(Handle<Map> map,
- Register scratch,
- Label* if_deprecated);
-
// Check if object is in new space. Jumps if the object is not in new space.
// The register scratch can be object itself, but scratch will be clobbered.
void JumpIfNotInNewSpace(Register object,
@@ -277,6 +273,9 @@ class MacroAssembler: public Assembler {
}
}
+ void CmpWeakValue(Register value, Handle<WeakCell> cell, Register scratch);
+ void LoadWeakValue(Register value, Handle<WeakCell> cell, Label* miss);
+
// ---------------------------------------------------------------------------
// JavaScript invokes
@@ -379,14 +378,12 @@ class MacroAssembler: public Assembler {
Label* fail,
SmiCheckType smi_check_type);
- // Check if the map of an object is equal to a specified map and branch to a
- // 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);
+ // Check if the map of an object is equal to a specified weak map and branch
+ // to a specified target if equal. Skip the smi check if not required
+ // (object is known to be a heap object)
+ void DispatchWeakMap(Register obj, Register scratch1, Register scratch2,
+ Handle<WeakCell> cell, Handle<Code> success,
+ SmiCheckType smi_check_type);
// Check if the object in register heap_object is a string. Afterwards the
// register map contains the object map and the register instance_type
@@ -458,7 +455,10 @@ class MacroAssembler: public Assembler {
j(not_carry, is_smi);
}
- void LoadUint32NoSSE2(Register src);
+ void LoadUint32NoSSE2(Register src) {
+ LoadUint32NoSSE2(Operand(src));
+ }
+ void LoadUint32NoSSE2(const Operand& src);
// Jump the register contains a smi.
inline void JumpIfSmi(Register value,
@@ -904,6 +904,7 @@ class MacroAssembler: public Assembler {
// Activation support.
void EnterFrame(StackFrame::Type type);
+ void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg);
void LeaveFrame(StackFrame::Type type);
// Expects object in eax and returns map with validated enum cache