Revert of Collect type profile for DevTools. (patchset #40 id:750001 of https://codereview.chromium.org/2707873002/ )

Reason for revert:
gcc bot is now flaky https://build.chromium.org/p/client.v8/builders/V8%20Linux%20gcc%204.8/builds/11863

Original issue's description:
> Collect type profile for DevTools
>
> Collect type information for JavaScript variables and display it
> in Chrome DevTools.
> Design Doc: https://docs.google.com/a/google.com/document/d/1O1uepXZXBI6IwiawTrYC3ohhiNgzkyTdjn3R8ysbYgk/edit?usp=sharing
>
> When debugging JavaScript, it’s helpful to know the type of
> a variable, parameter, and return values. JavaScript is
> dynamically typed, and for complex
> source code it’s often hard to infer types. With type profiling, we
> can provide type information to JavaScript developers.
>
> This CL is a proof of concept. It collects type profile for
> assignments and simply prints the types to stdout.
>
> The output looks something like this:
>
> #my_var1
>   #Object
>   #number
>   #string
>   #number
>   #undefined
>   #string
>   #Object
>   #Object
>
>
> We use an extra slot in the feedback vector of assignments to
> carry the list of types for that assignment. The extra slot is
> only added when the flag --type-profile is given.
>
>
> Missing work:
> * Collect data for parameters and return values (currently only assignments).
> * Remove duplicates from the list of collected types and use a common base class.
> * Add line numbers or source position instead of the variable name.
>
>
>
> BUG=v8:5935
>
> Review-Url: https://codereview.chromium.org/2707873002
> Cr-Original-Commit-Position: refs/heads/master@{#43791}
> Committed: 0332bebde9
> Review-Url: https://codereview.chromium.org/2707873002
> Cr-Commit-Position: refs/heads/master@{#43804}
> Committed: 6cf880f4b8

TBR=yangguo@chromium.org,mvstanton@chromium.org,rmcilroy@chromium.org,mstarzinger@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:5935

Review-Url: https://codereview.chromium.org/2754573002
Cr-Commit-Position: refs/heads/master@{#43805}
This commit is contained in:
franzih 2017-03-14 14:32:32 -07:00 committed by Commit bot
parent 6cf880f4b8
commit 14d0930d40
23 changed files with 11 additions and 3342 deletions

View File

@ -15,8 +15,7 @@ namespace internal {
class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
public:
AstNumberingVisitor(uintptr_t stack_limit, Zone* zone,
Compiler::EagerInnerFunctionLiterals* eager_literals,
bool collect_type_profile = false)
Compiler::EagerInnerFunctionLiterals* eager_literals)
: zone_(zone),
eager_literals_(eager_literals),
next_id_(BailoutId::FirstUsable().ToInt()),
@ -26,8 +25,7 @@ class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
slot_cache_(zone),
disable_crankshaft_reason_(kNoReason),
dont_optimize_reason_(kNoReason),
catch_prediction_(HandlerTable::UNCAUGHT),
collect_type_profile_(collect_type_profile) {
catch_prediction_(HandlerTable::UNCAUGHT) {
InitializeAstVisitor(stack_limit);
}
@ -103,7 +101,6 @@ class AstNumberingVisitor final : public AstVisitor<AstNumberingVisitor> {
BailoutReason disable_crankshaft_reason_;
BailoutReason dont_optimize_reason_;
HandlerTable::CatchPrediction catch_prediction_;
bool collect_type_profile_;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
DISALLOW_COPY_AND_ASSIGN(AstNumberingVisitor);
@ -425,8 +422,7 @@ void AstNumberingVisitor::VisitAssignment(Assignment* node) {
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
VisitReference(node->target());
Visit(node->value());
node->AssignFeedbackSlots(properties_.get_spec(), language_mode_,
&slot_cache_, collect_type_profile_);
ReserveFeedbackSlots(node);
}
@ -718,14 +714,12 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
bool AstNumbering::Renumber(
uintptr_t stack_limit, Zone* zone, FunctionLiteral* function,
Compiler::EagerInnerFunctionLiterals* eager_literals,
bool collect_type_profile) {
Compiler::EagerInnerFunctionLiterals* eager_literals) {
DisallowHeapAllocation no_allocation;
DisallowHandleAllocation no_handles;
DisallowHandleDereference no_deref;
AstNumberingVisitor visitor(stack_limit, zone, eager_literals,
collect_type_profile);
AstNumberingVisitor visitor(stack_limit, zone, eager_literals);
return visitor.Renumber(function);
}
} // namespace internal

View File

@ -27,8 +27,7 @@ namespace AstNumbering {
// non-null, adds any eager inner literal functions into it.
bool Renumber(
uintptr_t stack_limit, Zone* zone, FunctionLiteral* function,
ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* eager_literals,
bool collect_type_profile = false);
ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* eager_literals);
}
// Some details on yield IDs

View File

@ -283,13 +283,8 @@ Assignment::Assignment(Token::Value op, Expression* target, Expression* value,
void Assignment::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FeedbackSlotCache* cache,
bool collect_type_profile) {
FeedbackSlotCache* cache) {
AssignVectorSlots(target(), spec, language_mode, &slot_);
if (collect_type_profile) {
type_profile_slot_ = spec->AddTypeProfileSlot();
}
}
void CountOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,

View File

@ -2414,17 +2414,9 @@ class Assignment final : public Expression {
}
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FeedbackSlotCache* cache,
bool collect_type_profile = false);
FeedbackSlotCache* cache);
FeedbackSlot AssignmentSlot() const { return slot_; }
FeedbackSlot TypeProfileSlot() const {
DCHECK(HasTypeProfileSlot());
return type_profile_slot_;
}
bool HasTypeProfileSlot() const { return !type_profile_slot_.IsInvalid(); }
private:
friend class AstNodeFactory;
@ -2446,8 +2438,6 @@ class Assignment final : public Expression {
Expression* value_;
BinaryOperation* binary_operation_;
SmallMapList receiver_types_;
FeedbackSlot type_profile_slot_;
};

View File

@ -478,23 +478,9 @@ bool Renumber(ParseInfo* parse_info,
Compiler::EagerInnerFunctionLiterals* eager_literals) {
RuntimeCallTimerScope runtimeTimer(parse_info->isolate(),
&RuntimeCallStats::CompileRenumber);
// CollectTypeProfile uses its own feedback slots. If we have existing
// FeedbackMetadata, we can only collect type profile, if the feedback vector
// has the appropriate slots.
bool collect_type_profile;
if (parse_info->shared_info().is_null() ||
parse_info->shared_info()->feedback_metadata()->length() == 0) {
collect_type_profile = FLAG_type_profile;
} else {
collect_type_profile =
parse_info->shared_info()->feedback_metadata()->HasTypeProfileSlot();
}
if (!AstNumbering::Renumber(
parse_info->isolate()->stack_guard()->real_climit(),
parse_info->zone(), parse_info->literal(), eager_literals,
collect_type_profile)) {
parse_info->zone(), parse_info->literal(), eager_literals)) {
return false;
}
if (!parse_info->shared_info().is_null()) {

View File

@ -802,22 +802,6 @@ void BytecodeGraphBuilder::VisitStaDataPropertyInLiteral() {
environment()->RecordAfterState(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitCollectTypeProfile() {
PrepareEagerCheckpoint();
Node* name =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* value = environment()->LookupAccumulator();
Node* index = jsgraph()->Constant(bytecode_iterator().GetIndexOperand(1));
Node* vector = jsgraph()->Constant(feedback_vector());
const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
Node* node = NewNode(op, name, value, vector, index);
environment()->RecordAfterState(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitLdaContextSlot() {
const Operator* op = javascript()->LoadContext(
bytecode_iterator().GetUnsignedImmediateOperand(2),

View File

@ -54,7 +54,6 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
case FeedbackSlotKind::kToBoolean:
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kCreateClosure:
case FeedbackSlotKind::kTypeProfile:
return 1;
case FeedbackSlotKind::kCall:
@ -187,8 +186,7 @@ void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kTypeProfile: {
case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
with++;
} else if (obj == megamorphic_sentinel) {

View File

@ -149,8 +149,6 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
return "kCreateClosure";
case FeedbackSlotKind::kLiteral:
return "LITERAL";
case FeedbackSlotKind::kTypeProfile:
return "TYPE_PROFILE";
case FeedbackSlotKind::kGeneral:
return "STUB";
case FeedbackSlotKind::kKindsNumber:
@ -160,18 +158,6 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
return "?";
}
bool FeedbackMetadata::HasTypeProfileSlot() {
FeedbackMetadataIterator iter(this);
while (iter.HasNext()) {
iter.Next();
FeedbackSlotKind kind = iter.kind();
if (kind == FeedbackSlotKind::kTypeProfile) {
return true;
}
}
return false;
}
FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
DCHECK(!is_empty());
return metadata()->GetKind(slot);
@ -233,7 +219,6 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kGeneral:
case FeedbackSlotKind::kTypeProfile:
array->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
break;
@ -351,8 +336,7 @@ void FeedbackVector::ClearSlots(JSFunction* host_function) {
break;
}
case FeedbackSlotKind::kCreateClosure: {
case FeedbackSlotKind::kTypeProfile:
break;
break;
}
case FeedbackSlotKind::kGeneral: {
if (obj->IsHeapObject()) {
@ -1039,49 +1023,5 @@ void StoreDataPropertyInLiteralICNexus::ConfigureMonomorphic(
SetFeedbackExtra(*name);
}
InlineCacheState CollectTypeProfileNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* const feedback = GetFeedback();
if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
return UNINITIALIZED;
}
return MONOMORPHIC;
}
void CollectTypeProfileNexus::Collect(Handle<Name> type) {
Isolate* isolate = GetIsolate();
Object* const feedback = GetFeedback();
Handle<ArrayList> types;
if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
types = ArrayList::New(isolate, 1);
} else {
types = Handle<ArrayList>(ArrayList::cast(feedback), isolate);
}
// TODO(franzih): Somehow sort this list. Either avoid duplicates
// or use the common base type.
SetFeedback(*ArrayList::Add(types, type));
}
void CollectTypeProfileNexus::Print() const {
Isolate* isolate = GetIsolate();
Object* const feedback = GetFeedback();
if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
return;
}
Handle<ArrayList> list;
list = Handle<ArrayList>(ArrayList::cast(feedback), isolate);
for (int i = 0; i < list->Length(); i++) {
String* name = String::cast(list->Get(i));
PrintF("%s\n", name->ToCString().get());
}
}
} // namespace internal
} // namespace v8

View File

@ -36,7 +36,6 @@ enum class FeedbackSlotKind {
kCompareOp,
kToBoolean,
kStoreDataPropertyInLiteral,
kTypeProfile,
kCreateClosure,
kLiteral,
// This is a general purpose slot that occupies one feedback vector element.
@ -151,11 +150,6 @@ class FeedbackVectorSpecBase {
return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
}
FeedbackSlot AddTypeProfileSlot() {
DCHECK(FLAG_type_profile);
return AddSlot(FeedbackSlotKind::kTypeProfile);
}
#ifdef OBJECT_PRINT
// For gdb debugging.
void Print();
@ -256,8 +250,6 @@ class FeedbackMetadata : public FixedArray {
static const char* Kind2String(FeedbackSlotKind kind);
bool HasTypeProfileSlot();
private:
static const int kFeedbackSlotKindBits = 5;
STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
@ -750,30 +742,6 @@ class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
InlineCacheState StateFromFeedback() const override;
};
// For each assignment, store the type of the value in the collection of types
// in the feedback vector.
class CollectTypeProfileNexus : public FeedbackNexus {
public:
CollectTypeProfileNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
}
CollectTypeProfileNexus(FeedbackVector* vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK_EQ(FeedbackSlotKind::kTypeProfile, vector->GetKind(slot));
}
// Add a type to the list of types.
void Collect(Handle<Name> type);
// Dump the types to stdout.
// TODO(franzih): pass this information to the debugger protocol instead of
// stdout.
void Print() const;
InlineCacheState StateFromFeedback() const override;
};
inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);

View File

@ -581,7 +581,6 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kGeneral:
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kTypeProfile:
case FeedbackSlotKind::kInvalid:
case FeedbackSlotKind::kKindsNumber:
UNREACHABLE();
@ -629,7 +628,6 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kGeneral:
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kTypeProfile:
case FeedbackSlotKind::kInvalid:
case FeedbackSlotKind::kKindsNumber:
UNREACHABLE();

View File

@ -632,13 +632,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(
Register name, int feedback_slot) {
DCHECK(FLAG_type_profile);
OutputCollectTypeProfile(name, feedback_slot);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
Register object, size_t name_index, int feedback_slot,
LanguageMode language_mode) {

View File

@ -137,11 +137,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
Register object, Register name, DataPropertyInLiteralFlags flags,
int feedback_slot);
// Collect type information for developer tools. The value for which we
// record the type is stored in the accumulator.
// TODO(franzih): Do not pass the name, instead use the source position.
BytecodeArrayBuilder& CollectTypeProfile(Register name, int feedback_slot);
// Store a property named by a property name. The value to be stored should be
// in the accumulator.
BytecodeArrayBuilder& StoreNamedProperty(Register object,

View File

@ -2214,34 +2214,18 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
LhsKind assign_type = Property::GetAssignType(property);
// Evaluate LHS expression.
Register lhs_name;
if (expr->HasTypeProfileSlot()) {
lhs_name = register_allocator()->NewRegister();
}
switch (assign_type) {
case VARIABLE:
if (expr->HasTypeProfileSlot()) {
builder()
->LoadLiteral(expr->target()->AsVariableProxy()->var()->raw_name())
.StoreAccumulatorInRegister(lhs_name);
}
// Nothing to do to evaluate variable assignment LHS.
break;
case NAMED_PROPERTY: {
object = VisitForRegisterValue(property->obj());
name = property->key()->AsLiteral()->AsRawPropertyName();
if (expr->HasTypeProfileSlot()) {
builder()->LoadLiteral(name).StoreAccumulatorInRegister(lhs_name);
}
break;
}
case KEYED_PROPERTY: {
object = VisitForRegisterValue(property->obj());
key = VisitForRegisterValue(property->key());
if (expr->HasTypeProfileSlot()) {
builder()->StoreAccumulatorInRegister(lhs_name);
}
break;
}
case NAMED_SUPER_PROPERTY: {
@ -2254,9 +2238,6 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
.StoreAccumulatorInRegister(super_property_args[2]);
if (expr->HasTypeProfileSlot()) {
builder()->StoreAccumulatorInRegister(lhs_name);
}
break;
}
case KEYED_SUPER_PROPERTY: {
@ -2267,10 +2248,6 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
VisitForRegisterValue(super_property->home_object(),
super_property_args[1]);
VisitForRegisterValue(property->key(), super_property_args[2]);
if (expr->HasTypeProfileSlot()) {
builder()->StoreAccumulatorInRegister(lhs_name);
}
break;
}
}
@ -2359,14 +2336,6 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
break;
}
}
// Value is in accumulator.
if (expr->HasTypeProfileSlot()) {
FeedbackSlot collect_type_feedback_slot = expr->TypeProfileSlot();
builder()->CollectTypeProfile(lhs_name,
feedback_index(collect_type_feedback_slot));
}
}
void BytecodeGenerator::VisitYield(Yield* expr) {

View File

@ -105,8 +105,6 @@ namespace interpreter {
OperandType::kReg, OperandType::kIdx) \
V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kReg, OperandType::kFlag8, OperandType::kIdx) \
V(CollectTypeProfile, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kIdx) \
\
/* Binary Operators */ \
V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \

View File

@ -1045,19 +1045,6 @@ void Interpreter::DoStaDataPropertyInLiteral(InterpreterAssembler* assembler) {
__ Dispatch();
}
void Interpreter::DoCollectTypeProfile(InterpreterAssembler* assembler) {
Node* name = __ LoadRegister(__ BytecodeOperandReg(0));
Node* value = __ GetAccumulator();
Node* vector_index = __ SmiTag(__ BytecodeOperandIdx(1));
Node* feedback_vector = __ LoadFeedbackVector();
Node* context = __ GetContext();
__ CallRuntime(Runtime::kCollectTypeProfile, context, name, value,
feedback_vector, vector_index);
__ Dispatch();
}
// LdaModuleVariable <cell_index> <depth>
//
// Load the contents of a module variable into the accumulator. The variable is

View File

@ -751,7 +751,6 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
case FeedbackSlotKind::kCreateClosure:
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kGeneral:
case FeedbackSlotKind::kTypeProfile:
break;
case FeedbackSlotKind::kToBoolean:
case FeedbackSlotKind::kInvalid:

View File

@ -691,32 +691,6 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
return *object;
}
RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2);
CONVERT_SMI_ARG_CHECKED(index, 3);
DCHECK(FLAG_type_profile);
Handle<Name> type = Object::TypeOf(isolate, value);
if (value->IsJSReceiver()) {
Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
type = JSReceiver::GetConstructorName(object);
}
CollectTypeProfileNexus nexus(vector, vector->ToSlot(index));
nexus.Collect(type);
PrintF("%s\n", name->ToCString().get());
nexus.Print();
PrintF("\n");
return *name;
}
// Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(Runtime_GetDataProperty) {
HandleScope scope(isolate);

View File

@ -394,7 +394,6 @@ namespace internal {
F(IsJSGlobalProxy, 1, 1) \
F(DefineAccessorPropertyUnchecked, 5, 1) \
F(DefineDataPropertyInLiteral, 6, 1) \
F(CollectTypeProfile, 4, 1) \
F(GetDataProperty, 2, 1) \
F(GetConstructorName, 1, 1) \
F(HasFastPackedElements, 1, 1) \

View File

@ -1,440 +0,0 @@
// Copyright 2017 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: --type-profile
// Add mjsunit/array-splice.js as integration test for type profile.
const expression = `
function assertEquals() {
}
function assertFalse() {
}
function assertTrue() {
}
// Check that splicing array of holes keeps it as array of holes
(function() {
for (var i = 0; i < 7; i++) {
var array = new Array(10);
var spliced = array.splice(1, 1, 'one', 'two');
assertEquals(1, spliced.length);
assertFalse(0 in spliced, "0 in spliced");
assertEquals(11, array.length);
assertFalse(0 in array, "0 in array");
assertTrue(1 in array);
assertTrue(2 in array);
assertFalse(3 in array, "3 in array");
}
})();
// Check various variants of empty array's splicing.
(function() {
for (var i = 0; i < 7; i++) {
assertEquals([], [].splice(0, 0));
assertEquals([], [].splice(1, 0));
assertEquals([], [].splice(0, 1));
assertEquals([], [].splice(-1, 0));
}
})();
// Check that even if result array is empty, receiver gets sliced.
(function() {
for (var i = 0; i < 7; i++) {
var a = [1, 2, 3];
assertEquals([], a.splice(1, 0, 'a', 'b', 'c'));
assertEquals([1, 'a', 'b', 'c', 2, 3], a);
}
})();
// Check various forms of arguments omission.
(function() {
var array;
for (var i = 0; i < 7; i++) {
array = [1, 2, 3]
assertEquals([], array.splice());
assertEquals([1, 2, 3], array);
// SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
// given differently from when an undefined delete count is given.
// This does not follow ECMA-262, but we do the same for
// compatibility.
array = [1, 2, 3]
assertEquals([1, 2, 3], array.splice(0));
assertEquals([], array);
array = [1, 2, 3]
assertEquals([1, 2, 3], array.splice(undefined));
assertEquals([], array);
array = [1, 2, 3]
assertEquals([1, 2, 3], array.splice("foobar"));
assertEquals([], array);
array = [1, 2, 3]
assertEquals([], array.splice(undefined, undefined));
assertEquals([1, 2, 3], array);
array = [1, 2, 3]
assertEquals([], array.splice("foobar", undefined));
assertEquals([1, 2, 3], array);
array = [1, 2, 3]
assertEquals([], array.splice(undefined, "foobar"));
assertEquals([1, 2, 3], array);
array = [1, 2, 3]
assertEquals([], array.splice("foobar", "foobar"));
assertEquals([1, 2, 3], array);
}
})();
// Check variants of negatives and positive indices.
(function() {
var array, spliced;
for (var i = 0; i < 7; i++) {
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(-100);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(-1e100);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(-3);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(-3.999999);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(-3.000001);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(4);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(4.999999);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(4.000001);
assertEquals([1, 2, 3, 4], array);
assertEquals([5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(6);
assertEquals([1, 2, 3, 4, 5, 6], array);
assertEquals([7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(7);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(8);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(100);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(1e100);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, -100);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, -1e100);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, -3);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, -3.999999);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, -3.000001);
assertEquals([1, 2, 3, 4, 5, 6, 7], array);
assertEquals([], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 4);
assertEquals([5, 6, 7], array);
assertEquals([1, 2, 3, 4], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 4.999999);
assertEquals([5, 6, 7], array);
assertEquals([1, 2, 3, 4], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 4.000001);
assertEquals([5, 6, 7], array);
assertEquals([1, 2, 3, 4], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 6);
assertEquals([7], array);
assertEquals([1, 2, 3, 4, 5, 6], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 7);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 8);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 100);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
array = [1, 2, 3, 4, 5, 6, 7];
spliced = array.splice(0, 1e100);
assertEquals([], array);
assertEquals([1, 2, 3, 4, 5, 6, 7], spliced);
// Some exotic cases.
obj = { toString: function() { throw 'Exception'; } };
// Throwing an exception in conversion:
try {
[1, 2, 3].splice(obj, 3);
throw 'Should have thrown';
} catch (e) {
assertEquals('Exception', e);
}
try {
[1, 2, 3].splice(0, obj, 3);
throw 'Should have thrown';
} catch (e) {
assertEquals('Exception', e);
}
array = [1, 2, 3];
array.splice(0, 3, obj);
assertEquals(1, array.length);
// Custom conversion:
array = [1, 2, 3];
spliced = array.splice({valueOf: function() { return 1; }},
{toString: function() { return 2; }},
'one', 'two');
assertEquals([2, 3], spliced);
assertEquals([1, 'one', 'two'], array);
}
})();
// Nasty: modify the array in ToInteger.
(function() {
var array = [];
var spliced;
for (var i = 0; i < 13; i++) {
bad_start = { valueOf: function() { array.push(2*i); return -1; } };
bad_count = { valueOf: function() { array.push(2*i + 1); return 1; } };
spliced = array.splice(bad_start, bad_count);
// According to the spec (15.4.4.12), length is calculated before
// performing ToInteger on arguments. However, v8 ignores elements
// we add while converting, so we need corrective pushes.
array.push(2*i); array.push(2*i + 1);
if (i == 0) {
assertEquals([], spliced); // Length was 0, nothing to get.
assertEquals([0, 1], array);
} else {
// When we start splice, array is [0 .. 2*i - 1], so we get
// as a result [2*i], this element is removed from the array,
// but [2 * i, 2 * i + 1] are added.
assertEquals([2 * i - 1], spliced);
assertEquals(2 * i, array[i]);
assertEquals(2 * i + 1, array[i + 1]);
}
}
})();
// Check the behaviour when approaching maximal values for length.
(function() {
for (var i = 0; i < 7; i++) {
try {
new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
throw 'Should have thrown RangeError';
} catch (e) {
assertTrue(e instanceof RangeError);
}
// Check smi boundary
var bigNum = (1 << 30) - 3;
var array = new Array(bigNum);
array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
assertEquals(bigNum + 7, array.length);
}
})();
(function() {
for (var i = 0; i < 7; i++) {
var a = [7, 8, 9];
a.splice(0, 0, 1, 2, 3, 4, 5, 6);
assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a);
assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)");
assertEquals(undefined, a[10]);
}
})();
(function testSpliceDeleteDouble() {
var a = [1.1, 1.2, 1.3, 1.4];
a.splice(2, 1)
assertEquals([1.1, 1.2, 1.4], a);
})();
// Past this point the ArrayProtector is invalidated since we modify the
// Array.prototype.
// Check the case of JS builtin .splice()
(function() {
for (var i = 0; i < 7; i++) {
var array = [1, 2, 3, 4];
Array.prototype[3] = 'foo'; // To force JS builtin.
var spliced = array.splice();
assertEquals([], spliced);
assertEquals([1, 2, 3, 4], array);
}
})();
// Now check the case with array of holes and some elements on prototype.
(function() {
var len = 9;
var at3 = "@3";
var at7 = "@7";
for (var i = 0; i < 7; i++) {
var array = new Array(len);
var array_proto = [];
array_proto[3] = at3;
array_proto[7] = at7;
array.__proto__ = array_proto;
var spliced = array.splice(2, 2, 'one', undefined, 'two');
// Second hole (at index 3) of array turns into
// value of Array.prototype[3] while copying.
assertEquals([, at3], spliced);
assertEquals([, , 'one', undefined, 'two', , , at7, at7, ,], array);
// ... but array[3] and array[7] is actually a hole:
assertTrue(delete array_proto[3]);
assertEquals(undefined, array[3]);
assertTrue(delete array_proto[7]);
assertEquals(undefined, array[7]);
// and now check hasOwnProperty
assertFalse(array.hasOwnProperty(0), "array.hasOwnProperty(0)");
assertFalse(array.hasOwnProperty(1), "array.hasOwnProperty(1)");
assertTrue(array.hasOwnProperty(2));
assertTrue(array.hasOwnProperty(3));
assertTrue(array.hasOwnProperty(4));
assertFalse(array.hasOwnProperty(5), "array.hasOwnProperty(5)");
assertFalse(array.hasOwnProperty(6), "array.hasOwnProperty(6)");
assertFalse(array.hasOwnProperty(7), "array.hasOwnProperty(7)");
assertTrue(array.hasOwnProperty(8));
assertFalse(array.hasOwnProperty(9), "array.hasOwnProperty(9)");
// and now check couple of indices above length.
assertFalse(array.hasOwnProperty(10), "array.hasOwnProperty(10)");
assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)");
assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)");
assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)");
assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2),
"array.hasOwnProperty(Math.pow(2, 32) - 2)");
}
})();
// Now check the case with array of holes and some elements on prototype.
(function() {
var len = 9;
var at3 = "@3";
var at7 = "@7";
for (var i = 0; i < 7; i++) {
var array = new Array(len);
Array.prototype[3] = at3;
Array.prototype[7] = at7;
var spliced = array.splice(2, 2, 'one', undefined, 'two');
// Second hole (at index 3) of array turns into
// value of Array.prototype[3] while copying.
assertEquals([, at3], spliced);
assertEquals([, , 'one', undefined, 'two', , , at7, at7, ,], array);
// ... but array[3] and array[7] is actually a hole:
assertTrue(delete Array.prototype[3]);
assertEquals(undefined, array[3]);
assertTrue(delete Array.prototype[7]);
assertEquals(undefined, array[7]);
// and now check hasOwnProperty
assertFalse(array.hasOwnProperty(0), "array.hasOwnProperty(0)");
assertFalse(array.hasOwnProperty(1), "array.hasOwnProperty(1)");
assertTrue(array.hasOwnProperty(2));
assertTrue(array.hasOwnProperty(3));
assertTrue(array.hasOwnProperty(4));
assertFalse(array.hasOwnProperty(5), "array.hasOwnProperty(5)");
assertFalse(array.hasOwnProperty(6), "array.hasOwnProperty(6)");
assertFalse(array.hasOwnProperty(7), "array.hasOwnProperty(7)");
assertTrue(array.hasOwnProperty(8));
assertFalse(array.hasOwnProperty(9), "array.hasOwnProperty(9)");
// and now check couple of indices above length.
assertFalse(array.hasOwnProperty(10), "array.hasOwnProperty(10)");
assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)");
assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)");
assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)");
assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2),
"array.hasOwnProperty(Math.pow(2, 32) - 2)");
}
})();`;
Protocol.Runtime.evaluate({ expression: expression })
.then(function() {InspectorTest.completeTest();});

View File

@ -1,902 +0,0 @@
setTimeout
Function
.result
Function
attachInspector
Function
detachInspector
Function
setMaxAsyncTaskStacks
Function
breakProgram
Function
createObjectWithStrictCheck
Function
callWithScheduledBreak
Function
allowAccessorFormatting
Function
.result
Function
print
Function
quit
Function
setlocale
Function
read
Function
load
Function
compileAndRunWithOrigin
Function
setCurrentTimeMSForTest
Function
schedulePauseOnNextStatement
Function
cancelPauseOnNextStatement
Function
reconnect
Function
createContextGroup
Function
.result
Function
sendMessageToBackend
Function
.result
Function
.result
Function
InspectorTest
Object
_dispatchTable
Map
_requestId
number
_dumpInspectorProtocolMessages
boolean
_eventHandler
Object
Protocol
Object
log
Function
logMessage
Function
logObject
Function
logCallFrames
Function
logSourceLocation
Function
logSourceLocations
Function
logAsyncStackTrace
Function
completeTest
Function
completeTestAfterPendingTimeouts
Function
waitPendingTasks
Function
addScript
Function
addScriptWithUrl
Function
addModule
Function
startDumpingProtocolMessages
Function
sendRawCommand
Function
checkExpectation
Function
expectedSuccess
Function
expectedError
Function
setupScriptMap
Function
runTestSuite
Function
runAsyncTestSuite
AsyncFunction
_sendCommandPromise
Function
_waitForEventPromise
Function
_dispatchMessage
Function
loadScript
Function
.result
Function
expression
string
eventPattern
RegExp
match
object
requestId
number
messageObject
Object
fulfillCallback
Function
promise
Promise
l
object
n
number
m
number
m
number
m
number
m
number
m
number
m
number
m
number
m
number
m
number
m
number
o
number
q
number
q
number
y
number
z
number
A
number
q
number
B
number
o
number
C
number
.result
Promise
.result
Function
__proto__
object
__proto__
object
object
__proto__
object
object
object
my_var1
Object
my_var2
number
my_var1
Object
number
my_var2
number
number
my_var1
Object
number
string
my_var2
number
number
number
my_var1
Object
number
string
number
my_var2
number
number
number
number
my_var1
Object
number
string
number
undefined
my_var2
number
number
number
number
number
my_var1
Object
number
string
number
undefined
string
my_var2
number
number
number
number
number
number
my_var1
Object
number
string
number
undefined
string
Object
my_var2
number
number
number
number
number
number
number
my_var1
Object
number
string
number
undefined
string
Object
Object
my_var2
number
number
number
number
number
number
number
number
Function
MyClass
Function
my_var
MyClass
my_var
MyClass
Object
my_var
MyClass
Object
number
.result
undefined
type
string
messageId
number
l
object
n
number
m
number
number
m
number
number
m
number
number
m
number
number
m
number
number
m
number
number
m
number
number
m
number
number
m
number
o
number
number
q
number
number
r
number
q
number
handler
Function
l
object
n
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
number
m
number
number
m
number
o
number
number
number
q
number
number
number
r
number
number
q
number
y
number
z
number
B
number
.result
undefined
eventPattern
RegExp
RegExp
match
object
object
requestId
number
number
messageObject
Object
Object
fulfillCallback
Function
Function
promise
Promise
Promise
l
object
object
n
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
number
m
number
number
number
m
number
number
o
number
number
number
number
q
number
number
number
number
q
number
number
y
number
number
z
number
number
A
number
number
q
number
number
B
number
number
o
number
number
C
number
number
messageId
number
number
l
object
object
n
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
number
number
number
m
number
number
o
number
number
number
number
number
q
number
number
number
number
number
r
number
number
number
q
number
number
handler
Function
Function
l
object
object
n
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
number
number
m
number
number
number
number
m
number
number
o
number
number
number
number
number
number
q
number
number
number
number
number
number
r
number
number
number
number
q
number
number
y
number
number
z
number
number
B
number
number
.result
undefined

View File

@ -1,38 +0,0 @@
// Copyright 2016 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: --type-profile --turbo
const expression = `
function test(param) {
var my_var1 = param;
var my_var2 = 17;
}
test({});
test(123);
test('hello');
test(123);
test(undefined);
test('hello');
test({x: 12});
test({x: 12});
class MyClass {
constructor() {}
}
function testConstructorNames(param) {
var my_var = param;
}
testConstructorNames(new MyClass());
testConstructorNames({});
testConstructorNames(2);
`;
Protocol.Runtime.evaluate({ expression: expression })
.then(function() {InspectorTest.completeTest();});

View File

@ -446,12 +446,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
scorecard[Bytecodes::ToByte(Bytecode::kTestNull)] = 1;
}
if (!FLAG_type_profile) {
// Bytecode for CollectTypeProfile is only emitted when
// Type Information for DevTools is turned on.
scorecard[Bytecodes::ToByte(Bytecode::kCollectTypeProfile)] = 1;
}
// Check return occurs at the end and only once in the BytecodeArray.
CHECK_EQ(final_bytecode, Bytecode::kReturn);
CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);