Commit a504a184 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Make %Arguments composable with inlining.

This makes the C++ fallback implementations for the two intrinsics,
%Arguments and %ArgumentsLength composable with respect to inlining.
Using deoptimization information gives us accurate data here.

R=bmeurer@chromium.org
TEST=mjsunit/regress/regress-4374
BUG=v8:4374
LOG=n

Review URL: https://codereview.chromium.org/1328363002

Cr-Commit-Position: refs/heads/master@{#30654}
parent da830b0e
......@@ -238,6 +238,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kTraceExit:
return 0;
case Runtime::kInlineArguments:
case Runtime::kInlineArgumentsLength:
case Runtime::kInlineCall:
case Runtime::kInlineCallFunction:
case Runtime::kInlineDefaultConstructorCallSuper:
......
......@@ -527,23 +527,23 @@ RUNTIME_FUNCTION(Runtime_DefaultConstructorCallSuper) {
isolate, super_constructor,
Runtime::GetPrototype(isolate, actual_constructor));
// Find the frame that holds the actual arguments passed to the function.
it.AdvanceToArgumentsFrame();
JavaScriptFrame* frame = it.frame();
// Determine the actual arguments passed to the function.
int argument_count = 0;
base::SmartArrayPointer<Handle<Object>> arguments =
Runtime::GetCallerArguments(isolate, 0, &argument_count);
// Prepare the array containing all passed arguments.
int argument_count = frame->GetArgumentsLength();
Handle<FixedArray> elements =
isolate->factory()->NewUninitializedFixedArray(argument_count);
for (int i = 0; i < argument_count; ++i) {
elements->set(i, frame->GetParameter(i));
elements->set(i, *arguments[i]);
}
Handle<JSArray> arguments = isolate->factory()->NewJSArrayWithElements(
Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(
elements, FAST_ELEMENTS, argument_count);
// Call %reflect_construct(<super>, <args>, <new.target>) now.
Handle<JSFunction> reflect = isolate->reflect_construct();
Handle<Object> argv[] = {super_constructor, arguments, original_constructor};
Handle<Object> argv[] = {super_constructor, array, original_constructor};
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
......
......@@ -313,7 +313,7 @@ RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) {
// Find the arguments of the JavaScript function invocation that called
// into C++ code. Collect these in a newly allocated array of handles (possibly
// prefixed by a number of empty handles).
static base::SmartArrayPointer<Handle<Object> > GetCallerArguments(
base::SmartArrayPointer<Handle<Object>> Runtime::GetCallerArguments(
Isolate* isolate, int prefix_argc, int* total_argc) {
// Find frame containing arguments passed to the caller.
JavaScriptFrameIterator it(isolate);
......@@ -385,8 +385,8 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
// Get all arguments of calling function (Function.prototype.bind).
int argc = 0;
base::SmartArrayPointer<Handle<Object> > arguments =
GetCallerArguments(isolate, 0, &argc);
base::SmartArrayPointer<Handle<Object>> arguments =
Runtime::GetCallerArguments(isolate, 0, &argc);
// Don't count the this-arg.
if (argc > 0) {
RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
......@@ -487,8 +487,8 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
!Handle<JSFunction>::cast(bound_function)->shared()->bound());
int total_argc = 0;
base::SmartArrayPointer<Handle<Object> > param_data =
GetCallerArguments(isolate, bound_argc, &total_argc);
base::SmartArrayPointer<Handle<Object>> param_data =
Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
for (int i = 0; i < bound_argc; i++) {
param_data[i] = Handle<Object>(
bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate);
......
......@@ -1046,35 +1046,32 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
RUNTIME_FUNCTION(Runtime_ArgumentsLength) {
SealHandleScope shs(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 0);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
return Smi::FromInt(frame->GetArgumentsLength());
int argument_count = 0;
Runtime::GetCallerArguments(isolate, 0, &argument_count);
return Smi::FromInt(argument_count);
}
RUNTIME_FUNCTION(Runtime_Arguments) {
SealHandleScope shs(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
// Compute the frame holding the arguments.
JavaScriptFrameIterator it(isolate);
it.AdvanceToArgumentsFrame();
JavaScriptFrame* frame = it.frame();
// Get the actual number of provided arguments.
const uint32_t n = frame->ComputeParametersCount();
// Determine the actual arguments passed to the function.
int argument_count_signed = 0;
base::SmartArrayPointer<Handle<Object>> arguments =
Runtime::GetCallerArguments(isolate, 0, &argument_count_signed);
const uint32_t argument_count = argument_count_signed;
// Try to convert the key to an index. If successful and within
// index return the the argument from the frame.
uint32_t index = 0;
if (raw_key->ToArrayIndex(&index) && index < n) {
return frame->GetParameter(index);
if (raw_key->ToArrayIndex(&index) && index < argument_count) {
return *arguments[index];
}
HandleScope scope(isolate);
if (raw_key->IsSymbol()) {
Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) {
......@@ -1097,8 +1094,8 @@ RUNTIME_FUNCTION(Runtime_Arguments) {
// Try to convert the string key into an array index.
if (key->AsArrayIndex(&index)) {
if (index < n) {
return frame->GetParameter(index);
if (index < argument_count) {
return *arguments[index];
} else {
Handle<Object> initial_prototype(isolate->initial_object_prototype());
Handle<Object> result;
......@@ -1111,10 +1108,11 @@ RUNTIME_FUNCTION(Runtime_Arguments) {
// Handle special arguments properties.
if (String::Equals(isolate->factory()->length_string(), key)) {
return Smi::FromInt(n);
return Smi::FromInt(argument_count);
}
if (String::Equals(isolate->factory()->callee_string(), key)) {
JSFunction* function = frame->function();
JavaScriptFrameIterator it(isolate);
JSFunction* function = it.frame()->function();
if (is_strict(function->shared()->language_mode())) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
......
......@@ -1176,6 +1176,7 @@ class Runtime : public AllStatic {
Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
LanguageMode language_mode);
// TODO(mstarzinger): Remove this once %DefaultConstructorCallSuper is gone.
MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
Isolate* isolate, Handle<Object> object);
......@@ -1206,6 +1207,15 @@ class Runtime : public AllStatic {
static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
Handle<Object>);
// Find the arguments of the JavaScript function invocation that called
// into C++ code. Collect these in a newly allocated array of handles
// (possibly prefixed by a number of empty handles).
// TODO(mstarzinger): Temporary workaround until this is only used by the
// %_Arguments and %_ArgumentsLength intrinsics. Make this function local to
// runtime-scopes.cc then.
static base::SmartArrayPointer<Handle<Object>> GetCallerArguments(
Isolate* isolate, int prefix_argc, int* total_argc);
static bool AtomicIsLockFree(uint32_t size);
};
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --context-specialization
// Flags: --turbo-filter=f --turbo-inlining
var f = (function() {
var max = Math.max;
return function f() { return max(0, -1); };
})();
assertEquals(0, f());
%OptimizeFunctionOnNextCall(f);
assertEquals(0, f());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment