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}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index 60263b5..6bbd1a3 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -14,7 +14,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 {
@@ -268,66 +268,6 @@
}
-void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(
- Isolate* isolate) {
- WriteInt32ToHeapNumberStub stub1(isolate, a1, v0, a2, a3);
- WriteInt32ToHeapNumberStub stub2(isolate, a2, v0, a3, a0);
- stub1.GetCode();
- stub2.GetCode();
-}
-
-
-// See comment for class, this does NOT work for int32's that are in Smi range.
-void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) {
- Label max_negative_int;
- // the_int_ has the answer which is a signed int32 but not a Smi.
- // We test for the special value that has a different exponent.
- STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u);
- // Test sign, and save for later conditionals.
- __ And(sign(), the_int(), Operand(0x80000000u));
- __ Branch(&max_negative_int, eq, the_int(), Operand(0x80000000u));
-
- // Set up the correct exponent in scratch_. All non-Smi int32s have the same.
- // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).
- uint32_t non_smi_exponent =
- (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
- __ li(scratch(), Operand(non_smi_exponent));
- // Set the sign bit in scratch_ if the value was negative.
- __ or_(scratch(), scratch(), sign());
- // Subtract from 0 if the value was negative.
- __ subu(at, zero_reg, the_int());
- __ Movn(the_int(), at, sign());
- // We should be masking the implict first digit of the mantissa away here,
- // but it just ends up combining harmlessly with the last digit of the
- // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get
- // the most significant 1 to hit the last bit of the 12 bit sign and exponent.
- DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0);
- const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2;
- __ srl(at, the_int(), shift_distance);
- __ or_(scratch(), scratch(), at);
- __ sw(scratch(), FieldMemOperand(the_heap_number(),
- HeapNumber::kExponentOffset));
- __ sll(scratch(), the_int(), 32 - shift_distance);
- __ Ret(USE_DELAY_SLOT);
- __ sw(scratch(), FieldMemOperand(the_heap_number(),
- HeapNumber::kMantissaOffset));
-
- __ bind(&max_negative_int);
- // The max negative int32 is stored as a positive number in the mantissa of
- // a double because it uses a sign bit instead of using two's complement.
- // The actual mantissa bits stored are all 0 because the implicit most
- // significant 1 bit is not stored.
- non_smi_exponent += 1 << HeapNumber::kExponentShift;
- __ li(scratch(), Operand(HeapNumber::kSignMask | non_smi_exponent));
- __ sw(scratch(),
- FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset));
- __ mov(scratch(), zero_reg);
- __ Ret(USE_DELAY_SLOT);
- __ sw(scratch(),
- FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset));
-}
-
-
// Handle the case where the lhs and rhs are the same object.
// Equality is almost reflexive (everything but NaN), so this is a test
// for "identity and not NaN".
@@ -911,7 +851,7 @@
// double_scratch can be overwritten in the delay slot.
// Calculates square root of base. Check for the special case of
// Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
- __ Move(double_scratch, -V8_INFINITY);
+ __ Move(double_scratch, static_cast<double>(-V8_INFINITY));
__ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch);
__ neg_d(double_result, double_scratch);
@@ -931,13 +871,13 @@
// double_scratch can be overwritten in the delay slot.
// Calculates square root of base. Check for the special case of
// Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
- __ Move(double_scratch, -V8_INFINITY);
+ __ Move(double_scratch, static_cast<double>(-V8_INFINITY));
__ BranchF(USE_DELAY_SLOT, &done, NULL, eq, double_base, double_scratch);
__ Move(double_result, kDoubleRegZero);
// Add +0 to convert -0 to +0.
__ add_d(double_scratch, double_base, kDoubleRegZero);
- __ Move(double_result, 1);
+ __ Move(double_result, 1.);
__ sqrt_d(double_scratch, double_scratch);
__ div_d(double_result, double_result, double_scratch);
__ jmp(&done);
@@ -1053,7 +993,6 @@
void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
CEntryStub::GenerateAheadOfTime(isolate);
- WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
@@ -1094,22 +1033,18 @@
void CEntryStub::Generate(MacroAssembler* masm) {
// Called from JavaScript; parameters are on stack as if calling JS function
- // s0: number of arguments including receiver
- // s1: size of arguments excluding receiver
- // s2: pointer to builtin function
+ // a0: number of arguments including receiver
+ // a1: pointer to builtin function
// fp: frame pointer (restored after C call)
// sp: stack pointer (restored as callee's sp after C call)
// cp: current context (C callee-saved)
ProfileEntryHookStub::MaybeCallEntryHook(masm);
- // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
- // The reason for this is that these arguments would need to be saved anyway
- // so it's faster to set them up directly.
- // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
-
// Compute the argv pointer in a callee-saved register.
+ __ dsll(s1, a0, kPointerSizeLog2);
__ Daddu(s1, sp, s1);
+ __ Dsubu(s1, s1, kPointerSize);
// Enter the exit frame that transitions from JavaScript to C++.
FrameScope scope(masm, StackFrame::MANUAL);
@@ -1121,7 +1056,8 @@
// Prepare arguments for C routine.
// a0 = argc
- __ mov(a0, s0);
+ __ mov(s0, a0);
+ __ mov(s2, a1);
// a1 = argv (set in the delay slot after find_ra below).
// We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We
@@ -1405,6 +1341,40 @@
}
+void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
+ // Return address is in ra.
+ Label miss;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register index = LoadDescriptor::NameRegister();
+ Register scratch = a4;
+ Register result = v0;
+ DCHECK(!scratch.is(receiver) && !scratch.is(index));
+ 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();
+
+ StubRuntimeCallHelper call_helper;
+ char_at_generator.GenerateSlow(masm, call_helper);
+
+ __ bind(&miss);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
// Uses registers a0 to a4.
// Expected input (depending on whether args are in registers or on the stack):
// * object: a0 or at sp + 1 * kPointerSize.
@@ -1416,8 +1386,6 @@
void InstanceofStub::Generate(MacroAssembler* masm) {
// Call site inlining and patching implies arguments in registers.
DCHECK(HasArgsInRegisters() || !HasCallSiteInlineCheck());
- // ReturnTrueFalse is only implemented for inlined call sites.
- DCHECK(!ReturnTrueFalseObject() || HasCallSiteInlineCheck());
// Fixed register usage throughout the stub:
const Register object = a0; // Object (lhs).
@@ -1442,7 +1410,7 @@
// If there is a call site cache don't look in the global cache, but do the
// real lookup and update the call site cache.
- if (!HasCallSiteInlineCheck()) {
+ if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) {
Label miss;
__ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex);
__ Branch(&miss, ne, function, Operand(at));
@@ -1501,6 +1469,9 @@
if (!HasCallSiteInlineCheck()) {
__ mov(v0, zero_reg);
__ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);
+ if (ReturnTrueFalseObject()) {
+ __ LoadRoot(v0, Heap::kTrueValueRootIndex);
+ }
} else {
// Patch the call site to return true.
__ LoadRoot(v0, Heap::kTrueValueRootIndex);
@@ -1519,6 +1490,9 @@
if (!HasCallSiteInlineCheck()) {
__ li(v0, Operand(Smi::FromInt(1)));
__ StoreRoot(v0, Heap::kInstanceofCacheAnswerRootIndex);
+ if (ReturnTrueFalseObject()) {
+ __ LoadRoot(v0, Heap::kFalseValueRootIndex);
+ }
} else {
// Patch the call site to return false.
__ LoadRoot(v0, Heap::kFalseValueRootIndex);
@@ -1542,23 +1516,33 @@
__ Branch(&slow, ne, scratch, Operand(JS_FUNCTION_TYPE));
// Null is not instance of anything.
- __ Branch(&object_not_null,
- ne,
- scratch,
+ __ Branch(&object_not_null, ne, object,
Operand(isolate()->factory()->null_value()));
- __ li(v0, Operand(Smi::FromInt(1)));
+ if (ReturnTrueFalseObject()) {
+ __ LoadRoot(v0, Heap::kFalseValueRootIndex);
+ } else {
+ __ li(v0, Operand(Smi::FromInt(1)));
+ }
__ DropAndRet(HasArgsInRegisters() ? 0 : 2);
__ bind(&object_not_null);
// Smi values are not instances of anything.
__ JumpIfNotSmi(object, &object_not_null_or_smi);
- __ li(v0, Operand(Smi::FromInt(1)));
+ if (ReturnTrueFalseObject()) {
+ __ LoadRoot(v0, Heap::kFalseValueRootIndex);
+ } else {
+ __ li(v0, Operand(Smi::FromInt(1)));
+ }
__ DropAndRet(HasArgsInRegisters() ? 0 : 2);
__ bind(&object_not_null_or_smi);
// String values are not instances of anything.
__ IsObjectJSStringType(object, scratch, &slow);
- __ li(v0, Operand(Smi::FromInt(1)));
+ if (ReturnTrueFalseObject()) {
+ __ LoadRoot(v0, Heap::kFalseValueRootIndex);
+ } else {
+ __ li(v0, Operand(Smi::FromInt(1)));
+ }
__ DropAndRet(HasArgsInRegisters() ? 0 : 2);
// Slow-case. Tail call builtin.
@@ -1586,8 +1570,14 @@
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
- NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3,
- a4, &miss);
+ // Ensure that the vector and slot registers won't be clobbered before
+ // calling the miss handler.
+ DCHECK(!FLAG_vector_ics ||
+ !AreAliased(a4, a5, VectorLoadICDescriptor::VectorRegister(),
+ VectorLoadICDescriptor::SlotRegister()));
+
+ NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, a4,
+ a5, &miss);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
@@ -2539,14 +2529,14 @@
// A monomorphic miss (i.e, here the cache is not uninitialized) goes
// megamorphic.
- __ LoadRoot(at, Heap::kUninitializedSymbolRootIndex);
+ __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
__ Branch(&initialize, eq, a4, Operand(at));
// MegamorphicSentinel is an immortal immovable object (undefined) so no
// write-barrier is needed.
__ bind(&megamorphic);
__ dsrl(a4, a3, 32- kPointerSizeLog2);
__ Daddu(a4, a2, Operand(a4));
- __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex);
+ __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
__ jmp(&done);
@@ -2783,14 +2773,16 @@
DCHECK(!a4.is(object_));
// If the receiver is a smi trigger the non-string case.
- __ JumpIfSmi(object_, receiver_not_string_);
+ if (check_mode_ == RECEIVER_IS_UNKNOWN) {
+ __ JumpIfSmi(object_, receiver_not_string_);
- // Fetch the instance type of the receiver into result register.
- __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
- __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
- // If the receiver is not a string trigger the non-string case.
- __ And(a4, result_, Operand(kIsNotStringMask));
- __ Branch(receiver_not_string_, ne, a4, Operand(zero_reg));
+ // Fetch the instance type of the receiver into result register.
+ __ ld(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
+ __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
+ // If the receiver is not a string trigger the non-string case.
+ __ And(a4, result_, Operand(kIsNotStringMask));
+ __ Branch(receiver_not_string_, ne, a4, Operand(zero_reg));
+ }
// If the index is non-smi trigger the non-smi case.
__ JumpIfNotSmi(index_, &index_not_smi_);
@@ -2864,6 +2856,10 @@
void CallICStub::Generate(MacroAssembler* masm) {
// a1 - function
// a3 - slot id (Smi)
+ 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;
@@ -2902,27 +2898,71 @@
}
__ bind(&extra_checks_or_miss);
- Label miss;
+ Label uninitialized, miss;
- __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex);
+ __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&slow_start, eq, a4, Operand(at));
- __ LoadRoot(at, Heap::kUninitializedSymbolRootIndex);
- __ Branch(&miss, eq, a4, Operand(at));
- 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(a4);
- __ GetObjectType(a4, a5, a5);
- __ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE));
- __ dsrl(a4, a3, 32 - kPointerSizeLog2);
- __ Daddu(a4, a2, Operand(a4));
- __ LoadRoot(at, Heap::kMegamorphicSymbolRootIndex);
- __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
- __ Branch(&slow_start);
+ // The following cases attempt to handle MISS cases without going to the
+ // runtime.
+ if (FLAG_trace_ic) {
+ __ Branch(&miss);
}
- // We are here because tracing is on or we are going monomorphic.
+ __ LoadRoot(at, Heap::kuninitialized_symbolRootIndex);
+ __ Branch(&uninitialized, eq, a4, Operand(at));
+
+ // 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(a4);
+ __ GetObjectType(a4, a5, a5);
+ __ Branch(&miss, ne, a5, Operand(JS_FUNCTION_TYPE));
+ __ dsrl(a4, a3, 32 - kPointerSizeLog2);
+ __ Daddu(a4, a2, Operand(a4));
+ __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
+ __ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
+ // We have to update statistics for runtime profiling.
+ __ ld(a4, FieldMemOperand(a2, with_types_offset));
+ __ Dsubu(a4, a4, Operand(Smi::FromInt(1)));
+ __ sd(a4, FieldMemOperand(a2, with_types_offset));
+ __ ld(a4, FieldMemOperand(a2, generic_offset));
+ __ Daddu(a4, a4, Operand(Smi::FromInt(1)));
+ __ Branch(USE_DELAY_SLOT, &slow_start);
+ __ sd(a4, FieldMemOperand(a2, generic_offset)); // In delay slot.
+
+ __ bind(&uninitialized);
+
+ // We are going monomorphic, provided we actually have a JSFunction.
+ __ JumpIfSmi(a1, &miss);
+
+ // Goto miss case if we do not have a function.
+ __ GetObjectType(a1, a4, a4);
+ __ Branch(&miss, ne, a4, Operand(JS_FUNCTION_TYPE));
+
+ // Make sure the function is not the Array() function, which requires special
+ // behavior on MISS.
+ __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, a4);
+ __ Branch(&miss, eq, a1, Operand(a4));
+
+ // Update stats.
+ __ ld(a4, FieldMemOperand(a2, with_types_offset));
+ __ Daddu(a4, a4, Operand(Smi::FromInt(1)));
+ __ sd(a4, FieldMemOperand(a2, with_types_offset));
+
+ // Store the function.
+ __ dsrl(a4, a3, 32 - kPointerSizeLog2);
+ __ Daddu(a4, a2, Operand(a4));
+ __ Daddu(a4, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+ __ sd(a1, MemOperand(a4, 0));
+
+ // Update the write barrier.
+ __ mov(a5, a1);
+ __ RecordWrite(a2, a4, a5, kRAHasNotBeenSaved, kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+ __ Branch(&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);
@@ -3329,14 +3369,57 @@
// a1: instance type
// a2: length
// a3: from index (untagged)
- StringCharAtGenerator generator(
- v0, a3, a2, v0, &runtime, &runtime, &runtime, STRING_INDEX_IS_NUMBER);
+ StringCharAtGenerator generator(v0, a3, a2, v0, &runtime, &runtime, &runtime,
+ STRING_INDEX_IS_NUMBER, RECEIVER_IS_STRING);
generator.GenerateFast(masm);
__ DropAndRet(3);
generator.SkipSlow(masm, &runtime);
}
+void ToNumberStub::Generate(MacroAssembler* masm) {
+ // The ToNumber stub takes one argument in a0.
+ Label not_smi;
+ __ JumpIfNotSmi(a0, ¬_smi);
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ __ bind(¬_smi);
+
+ Label not_heap_number;
+ __ ld(a1, FieldMemOperand(a0, HeapObject::kMapOffset));
+ __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
+ // a0: object
+ // a1: instance type.
+ __ Branch(¬_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ __ bind(¬_heap_number);
+
+ Label not_string, slow_string;
+ __ Branch(¬_string, hs, a1, Operand(FIRST_NONSTRING_TYPE));
+ // Check if string has a cached array index.
+ __ ld(a2, FieldMemOperand(a0, String::kHashFieldOffset));
+ __ And(at, a2, Operand(String::kContainsCachedArrayIndexMask));
+ __ Branch(&slow_string, ne, at, Operand(zero_reg));
+ __ IndexFromHash(a2, a0);
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a0);
+ __ bind(&slow_string);
+ __ push(a0); // Push argument.
+ __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
+ __ bind(¬_string);
+
+ Label not_oddball;
+ __ Branch(¬_oddball, ne, a1, Operand(ODDBALL_TYPE));
+ __ Ret(USE_DELAY_SLOT);
+ __ ld(v0, FieldMemOperand(a0, Oddball::kToNumberOffset));
+ __ bind(¬_oddball);
+
+ __ push(a0); // Push argument.
+ __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
+}
+
+
void StringHelper::GenerateFlatOneByteStringEquals(
MacroAssembler* masm, Register left, Register right, Register scratch1,
Register scratch2, Register scratch3) {