Revert "[turbofan] Optimize access to the length property of functions"
This reverts commit 7eb8937bca
.
Reason for revert: crbug.com/1408957
Original change's description:
> [turbofan] Optimize access to the length property of functions
>
> When compiling to JavaScript a language that supports curryfication, it
> is convenient to be able to efficiently get the arity of a function to
> check for partial application.
>
> Change-Id: I6611b523b2c3795f1f8fb123f63f5b6d604d793d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4111447
> Reviewed-by: Jakob Linke <jgruber@chromium.org>
> Commit-Queue: Jakob Linke <jgruber@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#85409}
Fixed: chromium:1408957
Change-Id: I5200392af7532a864afd73fb0e88be9a2153a312
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4187075
Commit-Queue: Jakob Linke <jgruber@chromium.org>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#85428}
This commit is contained in:
parent
05a3ad7c72
commit
7a3a6e88bd
1
AUTHORS
1
AUTHORS
@ -147,7 +147,6 @@ Jan de Mooij <jandemooij@gmail.com>
|
|||||||
Janusz Majnert <jmajnert@gmail.com>
|
Janusz Majnert <jmajnert@gmail.com>
|
||||||
Javad Amiri <javad.amiri@anu.edu.au>
|
Javad Amiri <javad.amiri@anu.edu.au>
|
||||||
Jay Freeman <saurik@saurik.com>
|
Jay Freeman <saurik@saurik.com>
|
||||||
Jérôme Vouillon <jerome.vouillon@gmail.com>
|
|
||||||
Jesper van den Ende <jespertheend@gmail.com>
|
Jesper van den Ende <jespertheend@gmail.com>
|
||||||
Ji Qiu <qiuji@iscas.ac.cn>
|
Ji Qiu <qiuji@iscas.ac.cn>
|
||||||
Jiawen Geng <technicalcute@gmail.com>
|
Jiawen Geng <technicalcute@gmail.com>
|
||||||
|
@ -213,19 +213,6 @@ FieldAccess AccessBuilder::ForJSFunctionSharedFunctionInfo() {
|
|||||||
return access;
|
return access;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
FieldAccess AccessBuilder::ForSharedFunctionInfoLength() {
|
|
||||||
FieldAccess access = {kTaggedBase,
|
|
||||||
SharedFunctionInfo::kLengthOffset,
|
|
||||||
Handle<Name>(),
|
|
||||||
MaybeHandle<Map>(),
|
|
||||||
TypeCache::Get()->kArgumentsLengthType,
|
|
||||||
MachineType::Uint16(),
|
|
||||||
kNoWriteBarrier,
|
|
||||||
"SharedFunctionInfoLength"};
|
|
||||||
return access;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
FieldAccess AccessBuilder::ForJSFunctionFeedbackCell() {
|
FieldAccess AccessBuilder::ForJSFunctionFeedbackCell() {
|
||||||
FieldAccess access = {kTaggedBase, JSFunction::kFeedbackCellOffset,
|
FieldAccess access = {kTaggedBase, JSFunction::kFeedbackCellOffset,
|
||||||
|
@ -92,9 +92,6 @@ class V8_EXPORT_PRIVATE AccessBuilder final
|
|||||||
// Provides access to JSFunction::shared() field.
|
// Provides access to JSFunction::shared() field.
|
||||||
static FieldAccess ForJSFunctionSharedFunctionInfo();
|
static FieldAccess ForJSFunctionSharedFunctionInfo();
|
||||||
|
|
||||||
// Provides access to SharedFunctionInfo::length() field.
|
|
||||||
static FieldAccess ForSharedFunctionInfoLength();
|
|
||||||
|
|
||||||
// Provides access to JSFunction::feedback_cell() field.
|
// Provides access to JSFunction::feedback_cell() field.
|
||||||
static FieldAccess ForJSFunctionFeedbackCell();
|
static FieldAccess ForJSFunctionFeedbackCell();
|
||||||
|
|
||||||
|
@ -161,12 +161,6 @@ PropertyAccessInfo PropertyAccessInfo::StringLength(Zone* zone,
|
|||||||
return PropertyAccessInfo(zone, kStringLength, {}, {{receiver_map}, zone});
|
return PropertyAccessInfo(zone, kStringLength, {}, {{receiver_map}, zone});
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
PropertyAccessInfo PropertyAccessInfo::FunctionLength(Zone* zone,
|
|
||||||
MapRef receiver_map) {
|
|
||||||
return PropertyAccessInfo(zone, kFunctionLength, {}, {{receiver_map}, zone});
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
PropertyAccessInfo PropertyAccessInfo::DictionaryProtoDataConstant(
|
PropertyAccessInfo PropertyAccessInfo::DictionaryProtoDataConstant(
|
||||||
Zone* zone, MapRef receiver_map, JSObjectRef holder,
|
Zone* zone, MapRef receiver_map, JSObjectRef holder,
|
||||||
@ -349,8 +343,7 @@ bool PropertyAccessInfo::Merge(PropertyAccessInfo const* that,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case kNotFound:
|
case kNotFound:
|
||||||
case kStringLength:
|
case kStringLength: {
|
||||||
case kFunctionLength: {
|
|
||||||
DCHECK(unrecorded_dependencies_.empty());
|
DCHECK(unrecorded_dependencies_.empty());
|
||||||
DCHECK(that->unrecorded_dependencies_.empty());
|
DCHECK(that->unrecorded_dependencies_.empty());
|
||||||
AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
|
AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
|
||||||
@ -1049,14 +1042,6 @@ PropertyAccessInfo AccessInfoFactory::LookupSpecialFieldAccessor(
|
|||||||
}
|
}
|
||||||
return Invalid();
|
return Invalid();
|
||||||
}
|
}
|
||||||
// Check for JSFunction::length field accessor.
|
|
||||||
if (map.object()->IsJSFunctionMap()) {
|
|
||||||
if (Name::Equals(isolate(), name.object(),
|
|
||||||
isolate()->factory()->length_string())) {
|
|
||||||
return PropertyAccessInfo::FunctionLength(zone(), map);
|
|
||||||
}
|
|
||||||
return Invalid();
|
|
||||||
}
|
|
||||||
// Check for special JSObject field accessors.
|
// Check for special JSObject field accessors.
|
||||||
FieldIndex field_index;
|
FieldIndex field_index;
|
||||||
if (Accessors::IsJSObjectFieldAccessor(isolate(), map.object(), name.object(),
|
if (Accessors::IsJSObjectFieldAccessor(isolate(), map.object(), name.object(),
|
||||||
|
@ -65,8 +65,7 @@ class PropertyAccessInfo final {
|
|||||||
kFastAccessorConstant,
|
kFastAccessorConstant,
|
||||||
kDictionaryProtoAccessorConstant,
|
kDictionaryProtoAccessorConstant,
|
||||||
kModuleExport,
|
kModuleExport,
|
||||||
kStringLength,
|
kStringLength
|
||||||
kFunctionLength
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static PropertyAccessInfo NotFound(Zone* zone, MapRef receiver_map,
|
static PropertyAccessInfo NotFound(Zone* zone, MapRef receiver_map,
|
||||||
@ -92,7 +91,6 @@ class PropertyAccessInfo final {
|
|||||||
static PropertyAccessInfo ModuleExport(Zone* zone, MapRef receiver_map,
|
static PropertyAccessInfo ModuleExport(Zone* zone, MapRef receiver_map,
|
||||||
CellRef cell);
|
CellRef cell);
|
||||||
static PropertyAccessInfo StringLength(Zone* zone, MapRef receiver_map);
|
static PropertyAccessInfo StringLength(Zone* zone, MapRef receiver_map);
|
||||||
static PropertyAccessInfo FunctionLength(Zone* zone, MapRef receiver_map);
|
|
||||||
static PropertyAccessInfo Invalid(Zone* zone);
|
static PropertyAccessInfo Invalid(Zone* zone);
|
||||||
static PropertyAccessInfo DictionaryProtoDataConstant(
|
static PropertyAccessInfo DictionaryProtoDataConstant(
|
||||||
Zone* zone, MapRef receiver_map, JSObjectRef holder,
|
Zone* zone, MapRef receiver_map, JSObjectRef holder,
|
||||||
@ -115,7 +113,6 @@ class PropertyAccessInfo final {
|
|||||||
}
|
}
|
||||||
bool IsModuleExport() const { return kind() == kModuleExport; }
|
bool IsModuleExport() const { return kind() == kModuleExport; }
|
||||||
bool IsStringLength() const { return kind() == kStringLength; }
|
bool IsStringLength() const { return kind() == kStringLength; }
|
||||||
bool IsFunctionLength() const { return kind() == kFunctionLength; }
|
|
||||||
bool IsDictionaryProtoDataConstant() const {
|
bool IsDictionaryProtoDataConstant() const {
|
||||||
return kind() == kDictionaryProtoDataConstant;
|
return kind() == kDictionaryProtoDataConstant;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,6 @@ class EffectControlLinearizer {
|
|||||||
Node* LowerStringEqual(Node* node);
|
Node* LowerStringEqual(Node* node);
|
||||||
Node* LowerStringLessThan(Node* node);
|
Node* LowerStringLessThan(Node* node);
|
||||||
Node* LowerStringLessThanOrEqual(Node* node);
|
Node* LowerStringLessThanOrEqual(Node* node);
|
||||||
Node* LowerFunctionLength(Node* node);
|
|
||||||
Node* LowerBigIntAdd(Node* node, Node* frame_state);
|
Node* LowerBigIntAdd(Node* node, Node* frame_state);
|
||||||
Node* LowerBigIntSubtract(Node* node, Node* frame_state);
|
Node* LowerBigIntSubtract(Node* node, Node* frame_state);
|
||||||
Node* LowerBigIntMultiply(Node* node, Node* frame_state);
|
Node* LowerBigIntMultiply(Node* node, Node* frame_state);
|
||||||
@ -1276,9 +1275,6 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
|||||||
case IrOpcode::kStringLessThanOrEqual:
|
case IrOpcode::kStringLessThanOrEqual:
|
||||||
result = LowerStringLessThanOrEqual(node);
|
result = LowerStringLessThanOrEqual(node);
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kFunctionLength:
|
|
||||||
result = LowerFunctionLength(node);
|
|
||||||
break;
|
|
||||||
case IrOpcode::kBigIntAdd:
|
case IrOpcode::kBigIntAdd:
|
||||||
result = LowerBigIntAdd(node, frame_state);
|
result = LowerBigIntAdd(node, frame_state);
|
||||||
break;
|
break;
|
||||||
@ -4581,14 +4577,6 @@ Node* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
|
|||||||
Builtins::CallableFor(isolate(), Builtin::kStringLessThanOrEqual), node);
|
Builtins::CallableFor(isolate(), Builtin::kStringLessThanOrEqual), node);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* EffectControlLinearizer::LowerFunctionLength(Node* node) {
|
|
||||||
Node* subject = node->InputAt(0);
|
|
||||||
|
|
||||||
auto shared =
|
|
||||||
__ LoadField(AccessBuilder::ForJSFunctionSharedFunctionInfo(), subject);
|
|
||||||
return __ LoadField(AccessBuilder::ForSharedFunctionInfoLength(), shared);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* EffectControlLinearizer::LowerBigIntAdd(Node* node, Node* frame_state) {
|
Node* EffectControlLinearizer::LowerBigIntAdd(Node* node, Node* frame_state) {
|
||||||
Node* lhs = node->InputAt(0);
|
Node* lhs = node->InputAt(0);
|
||||||
Node* rhs = node->InputAt(1);
|
Node* rhs = node->InputAt(1);
|
||||||
|
@ -2798,9 +2798,6 @@ JSNativeContextSpecialization::BuildPropertyLoad(
|
|||||||
} else if (access_info.IsStringLength()) {
|
} else if (access_info.IsStringLength()) {
|
||||||
DCHECK_EQ(receiver, lookup_start_object);
|
DCHECK_EQ(receiver, lookup_start_object);
|
||||||
value = graph()->NewNode(simplified()->StringLength(), receiver);
|
value = graph()->NewNode(simplified()->StringLength(), receiver);
|
||||||
} else if (access_info.IsFunctionLength()) {
|
|
||||||
DCHECK_EQ(receiver, lookup_start_object);
|
|
||||||
value = graph()->NewNode(simplified()->FunctionLength(), receiver);
|
|
||||||
} else {
|
} else {
|
||||||
DCHECK(access_info.IsDataField() || access_info.IsFastDataConstant() ||
|
DCHECK(access_info.IsDataField() || access_info.IsFastDataConstant() ||
|
||||||
access_info.IsDictionaryProtoDataConstant());
|
access_info.IsDictionaryProtoDataConstant());
|
||||||
|
@ -523,7 +523,6 @@
|
|||||||
V(StringToLowerCaseIntl) \
|
V(StringToLowerCaseIntl) \
|
||||||
V(StringToNumber) \
|
V(StringToNumber) \
|
||||||
V(StringToUpperCaseIntl) \
|
V(StringToUpperCaseIntl) \
|
||||||
V(FunctionLength) \
|
|
||||||
V(ToBoolean) \
|
V(ToBoolean) \
|
||||||
V(TransitionAndStoreElement) \
|
V(TransitionAndStoreElement) \
|
||||||
V(TransitionAndStoreNonNumberElement) \
|
V(TransitionAndStoreNonNumberElement) \
|
||||||
|
@ -3595,11 +3595,6 @@ class RepresentationSelector {
|
|||||||
MachineRepresentation::kTaggedPointer);
|
MachineRepresentation::kTaggedPointer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case IrOpcode::kFunctionLength: {
|
|
||||||
VisitUnop<T>(node, UseInfo::AnyTagged(),
|
|
||||||
MachineRepresentation::kWord32);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case IrOpcode::kCheckBounds:
|
case IrOpcode::kCheckBounds:
|
||||||
return VisitCheckBounds<T>(node, lowering);
|
return VisitCheckBounds<T>(node, lowering);
|
||||||
case IrOpcode::kCheckHeapObject: {
|
case IrOpcode::kCheckHeapObject: {
|
||||||
|
@ -808,7 +808,6 @@ bool operator==(CheckMinusZeroParameters const& lhs,
|
|||||||
V(StringLength, Operator::kNoProperties, 1, 0) \
|
V(StringLength, Operator::kNoProperties, 1, 0) \
|
||||||
V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0) \
|
V(StringToLowerCaseIntl, Operator::kNoProperties, 1, 0) \
|
||||||
V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0) \
|
V(StringToUpperCaseIntl, Operator::kNoProperties, 1, 0) \
|
||||||
V(FunctionLength, Operator::kNoProperties, 1, 0) \
|
|
||||||
V(TypeOf, Operator::kNoProperties, 1, 1) \
|
V(TypeOf, Operator::kNoProperties, 1, 1) \
|
||||||
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
|
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1, 0) \
|
||||||
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
|
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1, 0) \
|
||||||
|
@ -911,8 +911,6 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
|||||||
const Operator* StringToUpperCaseIntl();
|
const Operator* StringToUpperCaseIntl();
|
||||||
const Operator* StringSubstring();
|
const Operator* StringSubstring();
|
||||||
|
|
||||||
const Operator* FunctionLength();
|
|
||||||
|
|
||||||
const Operator* FindOrderedHashMapEntryForInt32Key();
|
const Operator* FindOrderedHashMapEntryForInt32Key();
|
||||||
const Operator* FindOrderedCollectionEntry(CollectionKind collection_kind);
|
const Operator* FindOrderedCollectionEntry(CollectionKind collection_kind);
|
||||||
|
|
||||||
|
@ -2287,10 +2287,6 @@ Type Typer::Visitor::TypeStringLength(Node* node) {
|
|||||||
|
|
||||||
Type Typer::Visitor::TypeStringSubstring(Node* node) { return Type::String(); }
|
Type Typer::Visitor::TypeStringSubstring(Node* node) { return Type::String(); }
|
||||||
|
|
||||||
Type Typer::Visitor::TypeFunctionLength(Node* node) {
|
|
||||||
return Type::Range(0, InstructionStream::kMaxArguments, zone());
|
|
||||||
}
|
|
||||||
|
|
||||||
Type Typer::Visitor::TypeCheckBounds(Node* node) {
|
Type Typer::Visitor::TypeCheckBounds(Node* node) {
|
||||||
return typer_->operation_typer_.CheckBounds(Operand(node, 0),
|
return typer_->operation_typer_.CheckBounds(Operand(node, 0),
|
||||||
Operand(node, 1));
|
Operand(node, 1));
|
||||||
|
@ -1227,10 +1227,6 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
|||||||
CheckValueInputIs(node, 2, Type::SignedSmall());
|
CheckValueInputIs(node, 2, Type::SignedSmall());
|
||||||
CheckTypeIs(node, Type::String());
|
CheckTypeIs(node, Type::String());
|
||||||
break;
|
break;
|
||||||
case IrOpcode::kFunctionLength:
|
|
||||||
CheckValueInputIs(node, 0, Type::Any());
|
|
||||||
CheckTypeIs(node, TypeCache::Get()->kArgumentsLengthType);
|
|
||||||
break;
|
|
||||||
case IrOpcode::kReferenceEqual:
|
case IrOpcode::kReferenceEqual:
|
||||||
CheckTypeIs(node, Type::Boolean());
|
CheckTypeIs(node, Type::Boolean());
|
||||||
break;
|
break;
|
||||||
|
@ -2481,22 +2481,6 @@ void StringLength::GenerateCode(MaglevAssembler* masm,
|
|||||||
FieldMemOperand(object, String::kLengthOffset));
|
FieldMemOperand(object, String::kLengthOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionLength::SetValueLocationConstraints() {
|
|
||||||
UseRegister(object_input());
|
|
||||||
DefineAsRegister(this);
|
|
||||||
}
|
|
||||||
void FunctionLength::GenerateCode(MaglevAssembler* masm,
|
|
||||||
const ProcessingState& state) {
|
|
||||||
Register object = ToRegister(object_input());
|
|
||||||
__ AssertFunction(object);
|
|
||||||
UseScratchRegisterScope temps(masm);
|
|
||||||
Register shared = temps.AcquireX();
|
|
||||||
__ LoadTaggedPointerField(
|
|
||||||
shared, FieldMemOperand(object, JSFunction::kSharedFunctionInfoOffset));
|
|
||||||
__ Ldr(ToRegister(result()).W(),
|
|
||||||
FieldMemOperand(shared, SharedFunctionInfo::kLengthOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestUndetectable::SetValueLocationConstraints() {
|
void TestUndetectable::SetValueLocationConstraints() {
|
||||||
UseRegister(value());
|
UseRegister(value());
|
||||||
DefineAsRegister(this);
|
DefineAsRegister(this);
|
||||||
|
@ -1960,13 +1960,6 @@ bool MaglevGraphBuilder::TryBuildPropertyLoad(
|
|||||||
current_interpreter_frame_.accumulator(),
|
current_interpreter_frame_.accumulator(),
|
||||||
access_info);
|
access_info);
|
||||||
return true;
|
return true;
|
||||||
case compiler::PropertyAccessInfo::kFunctionLength:
|
|
||||||
DCHECK_EQ(receiver, lookup_start_object);
|
|
||||||
SetAccumulator(AddNewNode<FunctionLength>({receiver}));
|
|
||||||
RecordKnownProperty(lookup_start_object, name,
|
|
||||||
current_interpreter_frame_.accumulator(),
|
|
||||||
access_info);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,6 @@ class CompactInterpreterFrameState;
|
|||||||
V(SetPendingMessage) \
|
V(SetPendingMessage) \
|
||||||
V(StringAt) \
|
V(StringAt) \
|
||||||
V(StringLength) \
|
V(StringLength) \
|
||||||
V(FunctionLength) \
|
|
||||||
V(ToBoolean) \
|
V(ToBoolean) \
|
||||||
V(ToBooleanLogicalNot) \
|
V(ToBooleanLogicalNot) \
|
||||||
V(TaggedEqual) \
|
V(TaggedEqual) \
|
||||||
@ -4660,25 +4659,6 @@ class StringLength : public FixedInputValueNodeT<1, StringLength> {
|
|||||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionLength : public FixedInputValueNodeT<1, FunctionLength> {
|
|
||||||
using Base = FixedInputValueNodeT<1, FunctionLength>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FunctionLength(uint64_t bitfield) : Base(bitfield) {}
|
|
||||||
|
|
||||||
static constexpr OpProperties kProperties =
|
|
||||||
OpProperties::Reading() | OpProperties::Int32();
|
|
||||||
static constexpr
|
|
||||||
typename Base::InputTypes kInputTypes{ValueRepresentation::kTagged};
|
|
||||||
|
|
||||||
static constexpr int kObjectIndex = 0;
|
|
||||||
Input& object_input() { return input(kObjectIndex); }
|
|
||||||
|
|
||||||
void SetValueLocationConstraints();
|
|
||||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
|
||||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class DefineNamedOwnGeneric
|
class DefineNamedOwnGeneric
|
||||||
: public FixedInputValueNodeT<3, DefineNamedOwnGeneric> {
|
: public FixedInputValueNodeT<3, DefineNamedOwnGeneric> {
|
||||||
using Base = FixedInputValueNodeT<3, DefineNamedOwnGeneric>;
|
using Base = FixedInputValueNodeT<3, DefineNamedOwnGeneric>;
|
||||||
|
@ -1331,21 +1331,6 @@ void StringLength::GenerateCode(MaglevAssembler* masm,
|
|||||||
__ movl(ToRegister(result()), FieldOperand(object, String::kLengthOffset));
|
__ movl(ToRegister(result()), FieldOperand(object, String::kLengthOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionLength::SetValueLocationConstraints() {
|
|
||||||
UseRegister(object_input());
|
|
||||||
DefineAsRegister(this);
|
|
||||||
}
|
|
||||||
void FunctionLength::GenerateCode(MaglevAssembler* masm,
|
|
||||||
const ProcessingState& state) {
|
|
||||||
Register object = ToRegister(object_input());
|
|
||||||
__ AssertFunction(object);
|
|
||||||
__ LoadTaggedPointerField(
|
|
||||||
kScratchRegister,
|
|
||||||
FieldOperand(object, JSFunction::kSharedFunctionInfoOffset));
|
|
||||||
__ movl(ToRegister(result()),
|
|
||||||
FieldOperand(kScratchRegister, SharedFunctionInfo::kLengthOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Int32AddWithOverflow::SetValueLocationConstraints() {
|
void Int32AddWithOverflow::SetValueLocationConstraints() {
|
||||||
UseRegister(left_input());
|
UseRegister(left_input());
|
||||||
UseRegister(right_input());
|
UseRegister(right_input());
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright 2023 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 --turbofan --no-always-turbofan
|
|
||||||
|
|
||||||
function f(g) {
|
|
||||||
return g.length;
|
|
||||||
}
|
|
||||||
function g(x, y) {}
|
|
||||||
function h(x, y, z) {}
|
|
||||||
function OptimizeAndTest(fn) {
|
|
||||||
%PrepareFunctionForOptimization(fn);
|
|
||||||
assertEquals(1, fn(f));
|
|
||||||
assertEquals(2, fn(g));
|
|
||||||
assertEquals(3, fn(h));
|
|
||||||
|
|
||||||
%OptimizeFunctionOnNextCall(fn);
|
|
||||||
fn(g);
|
|
||||||
assertOptimized(fn);
|
|
||||||
|
|
||||||
assertEquals(1, fn(f));
|
|
||||||
assertEquals(2, fn(g));
|
|
||||||
assertEquals(3, fn(h));
|
|
||||||
assertOptimized(fn);
|
|
||||||
|
|
||||||
assertEquals(3, fn('abc'));
|
|
||||||
assertUnoptimized(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
OptimizeAndTest(f);
|
|
Loading…
Reference in New Issue
Block a user