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/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index e737801..602d3a0 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.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(rax, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
@@ -2013,125 +2002,6 @@
}
-void InstanceOfStub::Generate(MacroAssembler* masm) {
- Register const object = rdx; // Object (lhs).
- Register const function = rax; // Function (rhs).
- Register const object_map = rcx; // Map of {object}.
- Register const function_map = r8; // Map of {function}.
- Register const function_prototype = rdi; // Prototype of {function}.
-
- 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, Label::kNear);
-
- // 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;
- __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
- __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex);
- __ j(not_equal, &fast_case, Label::kNear);
- __ CompareRoot(object_map, Heap::kInstanceofCacheMapRootIndex);
- __ j(not_equal, &fast_case, Label::kNear);
- __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
- __ ret(0);
-
- // 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);
- __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
- __ j(not_equal, &slow_case);
- __ LoadRoot(rax, Heap::kFalseValueRootIndex);
- __ ret(0);
-
- // Fast-case: The {function} must be a valid JSFunction.
- __ bind(&fast_case);
- __ JumpIfSmi(function, &slow_case);
- __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map);
- __ j(not_equal, &slow_case);
-
- // Go to the runtime if the function is not a constructor.
- __ testb(FieldOperand(function_map, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsConstructor));
- __ j(zero, &slow_case);
-
- // Ensure that {function} has an instance prototype.
- __ testb(FieldOperand(function_map, Map::kBitFieldOffset),
- Immediate(1 << Map::kHasNonInstancePrototype));
- __ j(not_zero, &slow_case);
-
- // Get the "prototype" (or initial map) of the {function}.
- __ movp(function_prototype,
- FieldOperand(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;
- Register const function_prototype_map = kScratchRegister;
- __ CmpObjectType(function_prototype, MAP_TYPE, function_prototype_map);
- __ j(not_equal, &function_prototype_valid, Label::kNear);
- __ movp(function_prototype,
- FieldOperand(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.
- Label done, loop, fast_runtime_fallback;
- __ LoadRoot(rax, Heap::kTrueValueRootIndex);
- __ bind(&loop);
-
- __ testb(FieldOperand(object_map, Map::kBitFieldOffset),
- Immediate(1 << Map::kIsAccessCheckNeeded));
- __ j(not_zero, &fast_runtime_fallback, Label::kNear);
- __ CmpInstanceType(object_map, JS_PROXY_TYPE);
- __ j(equal, &fast_runtime_fallback, Label::kNear);
-
- __ movp(object, FieldOperand(object_map, Map::kPrototypeOffset));
- __ cmpp(object, function_prototype);
- __ j(equal, &done, Label::kNear);
- __ CompareRoot(object, Heap::kNullValueRootIndex);
- __ movp(object_map, FieldOperand(object, HeapObject::kMapOffset));
- __ j(not_equal, &loop);
- __ LoadRoot(rax, Heap::kFalseValueRootIndex);
- __ bind(&done);
- __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
- __ ret(0);
-
- // Found Proxy or access check needed: Call the runtime.
- __ bind(&fast_runtime_fallback);
- __ PopReturnAddressTo(kScratchRegister);
- __ Push(object);
- __ Push(function_prototype);
- __ PushReturnAddressFrom(kScratchRegister);
- // Invalidate the instanceof cache.
- __ Move(rax, Smi::FromInt(0));
- __ StoreRoot(rax, Heap::kInstanceofCacheFunctionRootIndex);
- __ TailCallRuntime(Runtime::kHasInPrototypeChain);
-
- // Slow-case: Call the %InstanceOf runtime function.
- __ bind(&slow_case);
- __ PopReturnAddressTo(kScratchRegister);
- __ Push(object);
- __ Push(function);
- __ PushReturnAddressFrom(kScratchRegister);
- __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
- : Runtime::kInstanceOf);
-}
-
-
// -------------------------------------------------------------------------
// StringCharCodeAtGenerator
@@ -3735,8 +3605,8 @@
__ bind(¬_array);
__ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
__ j(not_equal, &miss);
- 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, no_reg);
@@ -3877,8 +3747,8 @@
__ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex);
__ j(not_equal, &miss);
- 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, no_reg);
@@ -4449,15 +4319,15 @@
__ bind(&done_allocate);
// Initialize the JSObject fields.
- __ movp(Operand(rax, JSObject::kMapOffset), rcx);
+ __ movp(FieldOperand(rax, JSObject::kMapOffset), rcx);
__ LoadRoot(rbx, Heap::kEmptyFixedArrayRootIndex);
- __ movp(Operand(rax, JSObject::kPropertiesOffset), rbx);
- __ movp(Operand(rax, JSObject::kElementsOffset), rbx);
+ __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), rbx);
+ __ movp(FieldOperand(rax, JSObject::kElementsOffset), rbx);
STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
- __ leap(rbx, Operand(rax, JSObject::kHeaderSize));
+ __ leap(rbx, FieldOperand(rax, JSObject::kHeaderSize));
// ----------- S t a t e -------------
- // -- rax : result (untagged)
+ // -- rax : result (tagged)
// -- rbx : result fields (untagged)
// -- rdi : result end (untagged)
// -- rcx : initial map
@@ -4475,10 +4345,6 @@
{
// Initialize all in-object fields with undefined.
__ InitializeFieldsWithFiller(rbx, rdi, r11);
-
- // Add the object tag to make the JSObject real.
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ incp(rax);
__ Ret();
}
__ bind(&slack_tracking);
@@ -4498,10 +4364,6 @@
__ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex);
__ InitializeFieldsWithFiller(rdx, rdi, r11);
- // Add the object tag to make the JSObject real.
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ incp(rax);
-
// Check if we can finalize the instance size.
Label finalize;
STATIC_ASSERT(Map::kSlackTrackingCounterEnd == 1);
@@ -4532,10 +4394,10 @@
__ CallRuntime(Runtime::kAllocateInNewSpace);
__ Pop(rcx);
}
- STATIC_ASSERT(kHeapObjectTag == 1);
- __ decp(rax);
__ movzxbl(rbx, FieldOperand(rcx, Map::kInstanceSizeOffset));
__ leap(rdi, Operand(rax, rbx, times_pointer_size, 0));
+ STATIC_ASSERT(kHeapObjectTag == 1);
+ __ decp(rdi); // Remove the tag from the end address.
__ jmp(&done_allocate);
// Fall back to %NewObject.
@@ -4557,19 +4419,19 @@
// -----------------------------------
__ AssertFunction(rdi);
- // 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 rdx point to that
- // JavaScript frame.
- {
- Label loop, loop_entry;
- __ movp(rdx, rbp);
- __ jmp(&loop_entry, Label::kNear);
- __ bind(&loop);
+ // Make rdx point to the JavaScript frame.
+ __ movp(rdx, rbp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
__ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
- __ bind(&loop_entry);
+ }
+ if (FLAG_debug_code) {
+ Label ok;
__ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset));
- __ j(not_equal, &loop);
+ __ j(equal, &ok);
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
}
// Check if we have rest parameters (only possible if we have an
@@ -4601,7 +4463,7 @@
// Allocate an empty rest parameter array.
Label allocate, done_allocate;
- __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, TAG_OBJECT);
+ __ Allocate(JSArray::kSize, rax, rdx, rcx, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Setup the rest parameter array in rax.
@@ -4642,7 +4504,7 @@
Label allocate, done_allocate;
__ leal(rcx, Operand(rax, times_pointer_size,
JSArray::kSize + FixedArray::kHeaderSize));
- __ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT);
+ __ Allocate(rcx, rdx, rdi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Compute the arguments.length in rdi.
@@ -4709,11 +4571,26 @@
// -----------------------------------
__ AssertFunction(rdi);
+ // Make r9 point to the JavaScript frame.
+ __ movp(r9, rbp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
+ __ movp(r9, Operand(r9, StandardFrameConstants::kCallerFPOffset));
+ }
+ if (FLAG_debug_code) {
+ Label ok;
+ __ cmpp(rdi, Operand(r9, StandardFrameConstants::kFunctionOffset));
+ __ j(equal, &ok);
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
+ }
+
// TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub.
__ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ LoadSharedFunctionInfoSpecialField(
rcx, rcx, SharedFunctionInfo::kFormalParameterCountOffset);
- __ leap(rdx, Operand(rbp, rcx, times_pointer_size,
+ __ leap(rdx, Operand(r9, rcx, times_pointer_size,
StandardFrameConstants::kCallerSPOffset));
__ Integer32ToSmi(rcx, rcx);
@@ -4721,6 +4598,7 @@
// rdx : parameters pointer
// rdi : function
// rsp[0] : return address
+ // r9 : JavaScript frame pointer.
// Registers used over the whole function:
// rbx: the mapped parameter count (untagged)
// rax: the allocated object (tagged).
@@ -4731,7 +4609,7 @@
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, try_allocate, runtime;
- __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+ __ movp(rax, Operand(r9, StandardFrameConstants::kCallerFPOffset));
__ movp(r8, Operand(rax, CommonFrameConstants::kContextOrFrameTypeOffset));
__ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ j(equal, &adaptor_frame);
@@ -4774,7 +4652,7 @@
__ addp(r8, Immediate(JSSloppyArgumentsObject::kSize));
// Do the allocation of all three objects in one go.
- __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT);
+ __ Allocate(r8, rax, r9, no_reg, &runtime, NO_ALLOCATION_FLAGS);
// rax = address of new object(s) (tagged)
// r11 = argument count (untagged)
@@ -4927,19 +4805,19 @@
// -----------------------------------
__ AssertFunction(rdi);
- // 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 rdx point to that
- // JavaScript frame.
- {
- Label loop, loop_entry;
- __ movp(rdx, rbp);
- __ jmp(&loop_entry, Label::kNear);
- __ bind(&loop);
+ // Make rdx point to the JavaScript frame.
+ __ movp(rdx, rbp);
+ if (skip_stub_frame()) {
+ // For Ignition we need to skip the handler/stub frame to reach the
+ // JavaScript frame for the function.
__ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset));
- __ bind(&loop_entry);
+ }
+ if (FLAG_debug_code) {
+ Label ok;
__ cmpp(rdi, Operand(rdx, StandardFrameConstants::kFunctionOffset));
- __ j(not_equal, &loop);
+ __ j(equal, &ok);
+ __ Abort(kInvalidFrameForFastNewRestArgumentsStub);
+ __ bind(&ok);
}
// Check if we have an arguments adaptor frame below the function frame.
@@ -4978,7 +4856,7 @@
Label allocate, done_allocate;
__ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize +
FixedArray::kHeaderSize));
- __ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT);
+ __ Allocate(rcx, rdx, rdi, no_reg, &allocate, NO_ALLOCATION_FLAGS);
__ bind(&done_allocate);
// Compute the arguments.length in rdi.
@@ -5404,10 +5282,14 @@
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);
__ PopReturnAddressTo(return_address);
+ // new target
+ __ PushRoot(Heap::kUndefinedValueRootIndex);
+
// context save
__ Push(context);
@@ -5441,7 +5323,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;
PrepareCallApiFunction(masm, kApiStackSpace);
@@ -5453,8 +5335,6 @@
__ movp(StackSpaceOperand(1), scratch);
// FunctionCallbackInfo::length_.
__ Set(StackSpaceOperand(2), argc);
- // FunctionCallbackInfo::is_construct_call_.
- __ Set(StackSpaceOperand(3), 0);
#if defined(__MINGW64__) || defined(_WIN64)
Register arguments_arg = rcx;
@@ -5479,11 +5359,11 @@
ARGUMENTS_DONT_CONTAIN_RECEIVER);
Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
FCA::kArgsLength - FCA::kContextSaveIndex);
- Operand is_construct_call_operand = StackSpaceOperand(3);
+ Operand length_operand = StackSpaceOperand(2);
Operand return_value_operand = args_from_rbp.GetArgumentOperand(
this->is_store() ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset);
int stack_space = 0;
- Operand* stack_space_operand = &is_construct_call_operand;
+ Operand* stack_space_operand = &length_operand;
stack_space = argc + FCA::kArgsLength + 1;
stack_space_operand = nullptr;
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, callback_arg,
@@ -5493,14 +5373,6 @@
void CallApiGetterStub::Generate(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rsp[0] : return address
- // -- rsp[8] : name
- // -- rsp[16 .. (16 + kArgsLength*8)] : v8::PropertyCallbackInfo::args_
- // -- ...
- // -- r8 : api_function_address
- // -----------------------------------
-
#if defined(__MINGW64__) || defined(_WIN64)
Register getter_arg = r8;
Register accessor_info_arg = rdx;
@@ -5510,9 +5382,36 @@
Register accessor_info_arg = rsi;
Register name_arg = rdi;
#endif
- Register api_function_address = ApiGetterDescriptor::function_address();
- DCHECK(api_function_address.is(r8));
+ Register api_function_address = r8;
+ Register receiver = ApiGetterDescriptor::ReceiverRegister();
+ Register holder = ApiGetterDescriptor::HolderRegister();
+ Register callback = ApiGetterDescriptor::CallbackRegister();
Register scratch = rax;
+ DCHECK(!AreAliased(receiver, holder, callback, scratch));
+
+ // 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);
+
+ // Insert additional parameters into the stack frame above return address.
+ __ PopReturnAddressTo(scratch);
+ __ Push(receiver);
+ __ Push(FieldOperand(callback, AccessorInfo::kDataOffset));
+ __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
+ __ Push(kScratchRegister); // return value
+ __ Push(kScratchRegister); // return value default
+ __ PushAddress(ExternalReference::isolate_address(isolate()));
+ __ Push(holder);
+ __ Push(Smi::FromInt(0)); // should_throw_on_error -> false
+ __ Push(FieldOperand(callback, AccessorInfo::kNameOffset));
+ __ PushReturnAddressFrom(scratch);
// v8::PropertyCallbackInfo::args_ array and name handle.
const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
@@ -5539,8 +5438,11 @@
// It's okay if api_function_address == getter_arg
// but not accessor_info_arg or name_arg
- DCHECK(!api_function_address.is(accessor_info_arg) &&
- !api_function_address.is(name_arg));
+ DCHECK(!api_function_address.is(accessor_info_arg));
+ DCHECK(!api_function_address.is(name_arg));
+ __ movp(scratch, FieldOperand(callback, AccessorInfo::kJsGetterOffset));
+ __ movp(api_function_address,
+ FieldOperand(scratch, Foreign::kForeignAddressOffset));
// +3 is to skip prolog, return address and name handle.
Operand return_value_operand(
@@ -5550,7 +5452,6 @@
NULL);
}
-
#undef __
} // namespace internal