Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index fdb6c81..5702c78 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -53,12 +53,6 @@
}
-void ArrayNoArgumentConstructorStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- InitializeArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
-
void ArraySingleArgumentConstructorStub::InitializeDescriptor(
CodeStubDescriptor* descriptor) {
InitializeArrayConstructorDescriptor(isolate(), descriptor, 1);
@@ -71,11 +65,6 @@
}
-void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
- CodeStubDescriptor* descriptor) {
- InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
-}
-
void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
Address deopt_handler = Runtime::FunctionForId(Runtime::kArrayPush)->entry;
descriptor->Initialize(a0, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
@@ -1461,128 +1450,6 @@
}
-void InstanceOfStub::Generate(MacroAssembler* masm) {
- Register const object = a1; // Object (lhs).
- Register const function = a0; // Function (rhs).
- Register const object_map = a2; // Map of {object}.
- Register const function_map = a3; // Map of {function}.
- Register const function_prototype = a4; // Prototype of {function}.
- Register const scratch = a5;
-
- DCHECK(object.is(InstanceOfDescriptor::LeftRegister()));
- DCHECK(function.is(InstanceOfDescriptor::RightRegister()));
-
- // Check if {object} is a smi.
- Label object_is_smi;
- __ JumpIfSmi(object, &object_is_smi);
-
- // Lookup the {function} and the {object} map in the global instanceof cache.
- // Note: This is safe because we clear the global instanceof cache whenever
- // we change the prototype of any object.
- Label fast_case, slow_case;
- __ ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
- __ LoadRoot(at, Heap::kInstanceofCacheFunctionRootIndex);
- __ Branch(&fast_case, ne, function, Operand(at));
- __ LoadRoot(at, Heap::kInstanceofCacheMapRootIndex);
- __ Branch(&fast_case, ne, object_map, Operand(at));
- __ Ret(USE_DELAY_SLOT);
- __ LoadRoot(v0, Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
-
- // If {object} is a smi we can safely return false if {function} is a JS
- // function, otherwise we have to miss to the runtime and throw an exception.
- __ bind(&object_is_smi);
- __ JumpIfSmi(function, &slow_case);
- __ GetObjectType(function, function_map, scratch);
- __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
- __ Ret(USE_DELAY_SLOT);
- __ LoadRoot(v0, Heap::kFalseValueRootIndex); // In delay slot.
-
- // Fast-case: The {function} must be a valid JSFunction.
- __ bind(&fast_case);
- __ JumpIfSmi(function, &slow_case);
- __ GetObjectType(function, function_map, scratch);
- __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE));
-
- // Go to the runtime if the function is not a constructor.
- __ lbu(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
- __ And(at, scratch, Operand(1 << Map::kIsConstructor));
- __ Branch(&slow_case, eq, at, Operand(zero_reg));
-
- // Ensure that {function} has an instance prototype.
- __ And(at, scratch, Operand(1 << Map::kHasNonInstancePrototype));
- __ Branch(&slow_case, ne, at, Operand(zero_reg));
-
- // Get the "prototype" (or initial map) of the {function}.
- __ ld(function_prototype,
- FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
- __ AssertNotSmi(function_prototype);
-
- // Resolve the prototype if the {function} has an initial map. Afterwards the
- // {function_prototype} will be either the JSReceiver prototype object or the
- // hole value, which means that no instances of the {function} were created so
- // far and hence we should return false.
- Label function_prototype_valid;
- __ GetObjectType(function_prototype, scratch, scratch);
- __ Branch(&function_prototype_valid, ne, scratch, Operand(MAP_TYPE));
- __ ld(function_prototype,
- FieldMemOperand(function_prototype, Map::kPrototypeOffset));
- __ bind(&function_prototype_valid);
- __ AssertNotSmi(function_prototype);
-
- // Update the global instanceof cache with the current {object} map and
- // {function}. The cached answer will be set when it is known below.
- __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
- __ StoreRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
-
- // Loop through the prototype chain looking for the {function} prototype.
- // Assume true, and change to false if not found.
- Register const object_instance_type = function_map;
- Register const map_bit_field = function_map;
- Register const null = scratch;
- Register const result = v0;
-
- Label done, loop, fast_runtime_fallback;
- __ LoadRoot(result, Heap::kTrueValueRootIndex);
- __ LoadRoot(null, Heap::kNullValueRootIndex);
- __ bind(&loop);
-
- // Check if the object needs to be access checked.
- __ lbu(map_bit_field, FieldMemOperand(object_map, Map::kBitFieldOffset));
- __ And(map_bit_field, map_bit_field, Operand(1 << Map::kIsAccessCheckNeeded));
- __ Branch(&fast_runtime_fallback, ne, map_bit_field, Operand(zero_reg));
- // Check if the current object is a Proxy.
- __ lbu(object_instance_type,
- FieldMemOperand(object_map, Map::kInstanceTypeOffset));
- __ Branch(&fast_runtime_fallback, eq, object_instance_type,
- Operand(JS_PROXY_TYPE));
-
- __ ld(object, FieldMemOperand(object_map, Map::kPrototypeOffset));
- __ Branch(&done, eq, object, Operand(function_prototype));
- __ Branch(USE_DELAY_SLOT, &loop, ne, object, Operand(null));
- __ ld(object_map,
- FieldMemOperand(object, HeapObject::kMapOffset)); // In delay slot.
- __ LoadRoot(result, Heap::kFalseValueRootIndex);
- __ bind(&done);
- __ Ret(USE_DELAY_SLOT);
- __ StoreRoot(result,
- Heap::kInstanceofCacheAnswerRootIndex); // In delay slot.
-
- // Found Proxy or access check needed: Call the runtime
- __ bind(&fast_runtime_fallback);
- __ Push(object, function_prototype);
- // Invalidate the instanceof cache.
- DCHECK(Smi::FromInt(0) == 0);
- __ StoreRoot(zero_reg, Heap::kInstanceofCacheFunctionRootIndex);
- __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
- // Slow-case: Call the %InstanceOf runtime function.
- __ bind(&slow_case);
- __ Push(object, function);
- __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
- : Runtime::kInstanceOf);
-}
-
-
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
@@ -4046,8 +3913,8 @@
__ bind(¬_array);
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&miss, ne, feedback, Operand(at));
- Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
- Code::ComputeHandlerFlags(Code::LOAD_IC));
+ Code::Flags code_flags =
+ Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, Code::LOAD_IC, code_flags,
receiver, name, feedback,
receiver_map, scratch1, a7);
@@ -4189,8 +4056,8 @@
__ bind(¬_array);
__ Branch(&miss, ne, feedback, Heap::kmegamorphic_symbolRootIndex);
- Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
- Code::ComputeHandlerFlags(Code::STORE_IC));
+ Code::Flags code_flags =
+ Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(
masm, Code::STORE_IC, code_flags, receiver, key, feedback, receiver_map,
scratch1, scratch2);
@@ -4758,15 +4625,15 @@
__ bind(&done_allocate);
// Initialize the JSObject fields.
- __ sd(a2, MemOperand(v0, JSObject::kMapOffset));
+ __ sd(a2, FieldMemOperand(v0, JSObject::kMapOffset));
__ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex);
- __ sd(a3, MemOperand(v0, JSObject::kPropertiesOffset));
- __ sd(a3, MemOperand(v0, JSObject::kElementsOffset));
+ __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset));
+ __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset));
STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
- __ Daddu(a1, v0, Operand(JSObject::kHeaderSize));
+ __ Daddu(a1, v0, Operand(JSObject::kHeaderSize - kHeapObjectTag));
// ----------- S t a t e -------------
- // -- v0 : result (untagged)
+ // -- v0 : result (tagged)
// -- a1 : result fields (untagged)
// -- a5 : result end (untagged)
// -- a2 : initial map
@@ -4784,11 +4651,7 @@
{
// Initialize all in-object fields with undefined.
__ InitializeFieldsWithFiller(a1, a5, a0);
-
- // Add the object tag to make the JSObject real.
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ Ret(USE_DELAY_SLOT);
- __ Daddu(v0, v0, Operand(kHeapObjectTag)); // In delay slot.
+ __ Ret();
}
__ bind(&slack_tracking);
{
@@ -4811,9 +4674,7 @@
Label finalize;
STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
__ And(a3, a3, Operand(Map::ConstructionCounter::kMask));
- __ Branch(USE_DELAY_SLOT, &finalize, eq, a3, Operand(zero_reg));
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ Daddu(v0, v0, Operand(kHeapObjectTag)); // In delay slot.
+ __ Branch(&finalize, eq, a3, Operand(zero_reg));
__ Ret();
// Finalize the instance size.
@@ -4839,10 +4700,10 @@
__ CallRuntime(Runtime::kAllocateInNewSpace);
__ Pop(a2);
}
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ Dsubu(v0, v0, Operand(kHeapObjectTag));
__ lbu(a5, FieldMemOperand(a2, Map::kInstanceSizeOffset));
__ Dlsa(a5, v0, a5, kPointerSizeLog2);
+ STATIC_ASSERT(kHeapObjectTag == 1);
+ __ Dsubu(a5, a5, Operand(kHeapObjectTag));
__ jmp(&done_allocate);
// Fall back to %NewObject.
@@ -4861,19 +4722,19 @@
// -----------------------------------
__ AssertFunction(a1);
- // For Ignition we need to skip all possible handler/stub frames until
- // we reach the JavaScript frame for the function (similar to what the
- // runtime fallback implementation does). So make a2 point to that
- // JavaScript frame.
- {
- Label loop, loop_entry;
- __ Branch(USE_DELAY_SLOT, &loop_entry);
- __ mov(a2, fp); // In delay slot.
- __ bind(&loop);
+ // Make a2 point to the JavaScript frame.
+ __ mov(a2, fp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
__ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
- __ bind(&loop_entry);
+ }
+ if (FLAG_debug_code) {
+ Label ok;
__ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
- __ Branch(&loop, ne, a1, Operand(a3));
+ __ Branch(&ok, eq, a1, Operand(a3));
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
}
// Check if we have rest parameters (only possible if we have an
@@ -4905,7 +4766,7 @@
// Allocate an empty rest parameter array.
Label allocate, done_allocate;
- __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, TAG_OBJECT);
+ __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Setup the rest parameter array in v0.
@@ -4947,7 +4808,7 @@
Label allocate, done_allocate;
__ li(a1, Operand(JSArray::kSize + FixedArray::kHeaderSize));
__ Dlsa(a1, a1, a0, kPointerSizeLog2);
- __ Allocate(a1, v0, a3, a4, &allocate, TAG_OBJECT);
+ __ Allocate(a1, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Compute arguments.length in a4.
@@ -5007,24 +4868,40 @@
// -----------------------------------
__ AssertFunction(a1);
+ // Make t0 point to the JavaScript frame.
+ __ mov(t0, fp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
+ __ ld(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
+ }
+ if (FLAG_debug_code) {
+ Label ok;
+ __ ld(a3, MemOperand(t0, StandardFrameConstants::kFunctionOffset));
+ __ Branch(&ok, eq, a1, Operand(a3));
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
+ }
+
// TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
__ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a2,
FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset));
- __ Lsa(a3, fp, a2, kPointerSizeLog2);
+ __ Lsa(a3, t0, a2, kPointerSizeLog2);
__ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
__ SmiTag(a2);
// a1 : function
// a2 : number of parameters (tagged)
// a3 : parameters pointer
+ // t0 : Javascript frame pointer
// Registers used over whole function:
// a5 : arguments count (tagged)
// a6 : mapped parameter count (tagged)
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, try_allocate, runtime;
- __ ld(a4, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ ld(a4, MemOperand(t0, StandardFrameConstants::kCallerFPOffset));
__ ld(a0, MemOperand(a4, CommonFrameConstants::kContextOrFrameTypeOffset));
__ Branch(&adaptor_frame, eq, a0,
Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
@@ -5072,7 +4949,7 @@
__ Daddu(t1, t1, Operand(JSSloppyArgumentsObject::kSize));
// Do the allocation of all three objects in one go.
- __ Allocate(t1, v0, t1, a4, &runtime, TAG_OBJECT);
+ __ Allocate(t1, v0, t1, a4, &runtime, NO_ALLOCATION_FLAGS);
// v0 = address of new object(s) (tagged)
// a2 = argument count (smi-tagged)
@@ -5227,19 +5104,19 @@
// -----------------------------------
__ AssertFunction(a1);
- // For Ignition we need to skip all possible handler/stub frames until
- // we reach the JavaScript frame for the function (similar to what the
- // runtime fallback implementation does). So make a2 point to that
- // JavaScript frame.
- {
- Label loop, loop_entry;
- __ Branch(USE_DELAY_SLOT, &loop_entry);
- __ mov(a2, fp); // In delay slot.
- __ bind(&loop);
+ // Make a2 point to the JavaScript frame.
+ __ mov(a2, fp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
__ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
- __ bind(&loop_entry);
+ }
+ if (FLAG_debug_code) {
+ Label ok;
__ ld(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset));
- __ Branch(&loop, ne, a1, Operand(a3));
+ __ Branch(&ok, eq, a1, Operand(a3));
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
}
// Check if we have an arguments adaptor frame below the function frame.
@@ -5278,7 +5155,7 @@
Label allocate, done_allocate;
__ li(a1, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize));
__ Dlsa(a1, a1, a0, kPointerSizeLog2);
- __ Allocate(a1, v0, a3, a4, &allocate, TAG_OBJECT);
+ __ Allocate(a1, v0, a3, a4, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Compute arguments.length in a4.
@@ -5636,7 +5513,11 @@
STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
STATIC_ASSERT(FCA::kIsolateIndex == 1);
STATIC_ASSERT(FCA::kHolderIndex == 0);
- STATIC_ASSERT(FCA::kArgsLength == 7);
+ STATIC_ASSERT(FCA::kNewTargetIndex == 7);
+ STATIC_ASSERT(FCA::kArgsLength == 8);
+
+ // new target
+ __ PushRoot(Heap::kUndefinedValueRootIndex);
// Save context, callee and call data.
__ Push(context, callee, call_data);
@@ -5660,7 +5541,7 @@
// Allocate the v8::Arguments structure in the arguments' space since
// it's not controlled by GC.
- const int kApiStackSpace = 4;
+ const int kApiStackSpace = 3;
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ EnterExitFrame(false, kApiStackSpace);
@@ -5680,8 +5561,6 @@
// justified by n64 ABI.
__ li(at, Operand(argc()));
__ sw(at, MemOperand(a0, 2 * kPointerSize));
- // FunctionCallbackInfo::is_construct_call_ = 0
- __ sw(zero_reg, MemOperand(a0, 2 * kPointerSize + kIntSize));
ExternalReference thunk_ref =
ExternalReference::invoke_function_callback(masm->isolate());
@@ -5698,8 +5577,9 @@
}
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
int stack_space = 0;
- int32_t stack_space_offset = 4 * kPointerSize;
+ int32_t stack_space_offset = 3 * kPointerSize;
stack_space = argc() + FCA::kArgsLength + 1;
+ // TODO(adamk): Why are we clobbering this immediately?
stack_space_offset = kInvalidStackOffset;
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
stack_space_offset, return_value_operand,
@@ -5708,15 +5588,44 @@
void CallApiGetterStub::Generate(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- sp[0] : name
- // -- sp[8 .. (8 + kArgsLength*8)] : v8::PropertyCallbackInfo::args_
- // -- ...
- // -- a2 : api_function_address
- // -----------------------------------
+ // Build v8::PropertyCallbackInfo::args_ array on the stack and push property
+ // name below the exit frame to make GC aware of them.
+ STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0);
+ STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1);
+ STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2);
+ STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3);
+ STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4);
+ STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5);
+ STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6);
+ STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7);
- Register api_function_address = ApiGetterDescriptor::function_address();
- DCHECK(api_function_address.is(a2));
+ Register receiver = ApiGetterDescriptor::ReceiverRegister();
+ Register holder = ApiGetterDescriptor::HolderRegister();
+ Register callback = ApiGetterDescriptor::CallbackRegister();
+ Register scratch = a4;
+ DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+ Register api_function_address = a2;
+
+ // Here and below +1 is for name() pushed after the args_ array.
+ typedef PropertyCallbackArguments PCA;
+ __ Dsubu(sp, sp, (PCA::kArgsLength + 1) * kPointerSize);
+ __ sd(receiver, MemOperand(sp, (PCA::kThisIndex + 1) * kPointerSize));
+ __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kDataOffset));
+ __ sd(scratch, MemOperand(sp, (PCA::kDataIndex + 1) * kPointerSize));
+ __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+ __ sd(scratch, MemOperand(sp, (PCA::kReturnValueOffset + 1) * kPointerSize));
+ __ sd(scratch, MemOperand(sp, (PCA::kReturnValueDefaultValueIndex + 1) *
+ kPointerSize));
+ __ li(scratch, Operand(ExternalReference::isolate_address(isolate())));
+ __ sd(scratch, MemOperand(sp, (PCA::kIsolateIndex + 1) * kPointerSize));
+ __ sd(holder, MemOperand(sp, (PCA::kHolderIndex + 1) * kPointerSize));
+ // should_throw_on_error -> false
+ DCHECK(Smi::FromInt(0) == nullptr);
+ __ sd(zero_reg,
+ MemOperand(sp, (PCA::kShouldThrowOnErrorIndex + 1) * kPointerSize));
+ __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kNameOffset));
+ __ sd(scratch, MemOperand(sp, 0 * kPointerSize));
// v8::PropertyCallbackInfo::args_ array and name handle.
const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5738,6 +5647,10 @@
ExternalReference thunk_ref =
ExternalReference::invoke_accessor_getter_callback(isolate());
+ __ ld(scratch, FieldMemOperand(callback, AccessorInfo::kJsGetterOffset));
+ __ ld(api_function_address,
+ FieldMemOperand(scratch, Foreign::kForeignAddressOffset));
+
// +3 is to skip prolog, return address and name handle.
MemOperand return_value_operand(
fp, (PropertyCallbackArguments::kReturnValueOffset + 3) * kPointerSize);
@@ -5746,7 +5659,6 @@
return_value_operand, NULL);
}
-
#undef __
} // namespace internal