Commit 91e3243d authored by Swapnil Gaikwad's avatar Swapnil Gaikwad Committed by Commit Bot

Extend GetIterator bytecode to perform JSReceiver check on object[Symbol.iterator]()

Current GetIterator bytecode loads and calls @@iterator property on a
given object. This change extends the bytecode functionality to check
whether the value returned after calling @@iterator property is a valid
JSReceiver. The bytecode throws SymbolIteratorInvalid exception if the
returned value is not a valid JSReceiver. This change absorbs the
functionality of additional two bytecodes - JumpIfJSReceiver and
CallRuntime, that are part of the iterator protocol in the GetIterator
bytecode.

Bug: v8:9489
Change-Id: I9e84cfe85eeb9a1b8a97ca0595375ac26ba1bbfd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1792905Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Swapnil Gaikwad <swapnilgaikwad@google.com>
Cr-Commit-Position: refs/heads/master@{#63704}
parent 98c86c6b
......@@ -1710,6 +1710,8 @@ extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)(
Smi, Object, Object): void;
extern transitioning runtime ThrowCalledNonCallable(implicit context: Context)(
JSAny): never;
extern transitioning runtime ThrowSymbolIteratorInvalid(
implicit context: Context)(): never;
extern transitioning macro ThrowIfNotJSReceiver(implicit context: Context)(
JSAny, constexpr MessageTemplate, constexpr string): void;
......
......@@ -66,6 +66,14 @@ namespace iterator {
CollectCallFeedback(iteratorMethod, context, feedback, callSlotUnTagged);
const iteratorCallable: Callable = Cast<Callable>(iteratorMethod)
otherwise ThrowCalledNonCallable(iteratorMethod);
return Call(context, iteratorCallable, receiver);
const iterator: JSAny = Call(context, iteratorCallable, receiver);
typeswitch (iterator) {
case (JSReceiver): {
return iterator;
}
case (JSPrimitive): {
ThrowSymbolIteratorInvalid();
}
}
}
}
......@@ -1402,6 +1402,35 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* iterator_exception_node = nullptr;
Node* if_exception_merge = nullptr;
Node* if_exception_effect_phi = nullptr;
Node* if_exception_phi = nullptr;
bool has_exception_node =
NodeProperties::IsExceptionalCall(node, &iterator_exception_node);
if (has_exception_node) {
// If there exists an IfException node for the current {node}, we need
// exception handling for all the desugared nodes. Create a combination
// of Merge+Phi+EffectPhi nodes that consumes the exception paths from
// from all the desugared nodes including the original exception node.
// Usages of the original exception node are then rewired to the newly
// created combination of Merge+Phi+EffectPhi. Here, use dead_node as a
// placeholder for the original exception node until its uses are rewired.
Node* dead_node = jsgraph()->Dead();
if_exception_merge = graph()->NewNode(common()->Merge(1), dead_node);
if_exception_effect_phi =
graph()->NewNode(common()->EffectPhi(1), dead_node, if_exception_merge);
if_exception_phi =
graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 1),
dead_node, if_exception_merge);
ReplaceWithValue(iterator_exception_node, if_exception_phi,
if_exception_effect_phi, if_exception_merge);
if_exception_merge->ReplaceInput(0, iterator_exception_node);
if_exception_effect_phi->ReplaceInput(0, iterator_exception_node);
if_exception_phi->ReplaceInput(0, iterator_exception_node);
}
// Load iterator property operator
Handle<Name> iterator_symbol = factory()->iterator_symbol();
const Operator* load_op =
......@@ -1421,31 +1450,10 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
control = load_property;
// Handle exception path for the load named property
Node* iterator_exception_node = nullptr;
if (NodeProperties::IsExceptionalCall(node, &iterator_exception_node)) {
// If there exists an exception node for the given iterator_node, create a
// pair of IfException/IfSuccess nodes on the current control path. The uses
// of new exception node are merged with the original exception node. The
// IfSuccess node is returned as a control path for further reduction.
Node* exception_node =
graph()->NewNode(common()->IfException(), effect, control);
Node* if_success = graph()->NewNode(common()->IfSuccess(), control);
// Use dead_node as a placeholder for the original exception node until
// its uses are rewired to the nodes merging the exceptions
Node* dead_node = jsgraph()->Dead();
Node* merge_node =
graph()->NewNode(common()->Merge(2), dead_node, exception_node);
Node* effect_phi = graph()->NewNode(common()->EffectPhi(2), dead_node,
exception_node, merge_node);
Node* phi =
graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
dead_node, exception_node, merge_node);
ReplaceWithValue(iterator_exception_node, phi, effect_phi, merge_node);
phi->ReplaceInput(0, iterator_exception_node);
effect_phi->ReplaceInput(0, iterator_exception_node);
merge_node->ReplaceInput(0, iterator_exception_node);
control = if_success;
if (has_exception_node) {
control =
AppendExceptionHandling(effect, control, if_exception_merge,
if_exception_phi, if_exception_effect_phi);
}
// Eager deopt of call iterator property
......@@ -1468,8 +1476,46 @@ Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
ConvertReceiverMode::kNotNullOrUndefined, mode);
Node* call_property = graph()->NewNode(call_op, load_property, receiver,
context, frame_state, effect, control);
effect = call_property;
control = call_property;
if (has_exception_node) {
control =
AppendExceptionHandling(effect, control, if_exception_merge,
if_exception_phi, if_exception_effect_phi);
}
// Check if the call property returns a valid JSReceiver else throw an invalid
// iterator runtime exception
Node* is_receiver =
graph()->NewNode(simplified()->ObjectIsReceiver(), call_property);
Node* branch_node = graph()->NewNode(
common()->Branch(BranchHint::kNone, IsSafetyCheck::kNoSafetyCheck),
is_receiver, control);
{
// Create a version of effect and control for the false path of the branch
Node* effect = call_property;
Node* control = call_property;
Node* if_not_receiver = graph()->NewNode(common()->IfFalse(), branch_node);
control = if_not_receiver;
const Operator* call_runtime_op =
javascript()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid, 0);
Node* call_runtime = graph()->NewNode(call_runtime_op, context, frame_state,
effect, control);
control = call_runtime;
effect = call_runtime;
if (has_exception_node) {
control =
AppendExceptionHandling(effect, control, if_exception_merge,
if_exception_phi, if_exception_effect_phi);
}
Node* throw_node =
graph()->NewNode(common()->Throw(), call_runtime, control);
NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
}
return Replace(call_property);
Node* if_receiver = graph()->NewNode(common()->IfTrue(), branch_node);
ReplaceWithValue(node, call_property, effect, if_receiver);
return Replace(if_receiver);
}
Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
......@@ -3237,6 +3283,22 @@ Node* JSNativeContextSpecialization::BuildCheckEqualsName(NameRef const& name,
control);
}
Node* JSNativeContextSpecialization::AppendExceptionHandling(
Node* effect, Node* control, Node* merge, Node* phi, Node* effect_phi) {
DCHECK_EQ(effect, control);
int input_count = merge->InputCount() + 1;
Node* if_exception =
graph()->NewNode(common()->IfException(), effect, control);
merge->InsertInput(graph()->zone(), 0, if_exception);
NodeProperties::ChangeOp(merge, common()->Merge(input_count));
phi->InsertInput(graph()->zone(), 0, if_exception);
NodeProperties::ChangeOp(
phi, common()->Phi(MachineRepresentation::kTagged, input_count));
effect_phi->InsertInput(graph()->zone(), 0, if_exception);
NodeProperties::ChangeOp(effect_phi, common()->EffectPhi(input_count));
return graph()->NewNode(common()->IfSuccess(), control);
}
bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
ZoneVector<Handle<Map>> const& receiver_maps) {
// Check if all {receiver_maps} have one of the initial Array.prototype
......
......@@ -207,6 +207,12 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
Node* control);
// Attach a pair of success and exception paths on a given control path.
// The exception is joined to the Merge+Phi+EffectPhi nodes while the success
// path is returned.
Node* AppendExceptionHandling(Node* effect, Node* control, Node* merge,
Node* phi, Node* effect_phi);
// Checks if we can turn the hole into undefined when loading an element
// from an object with one of the {receiver_maps}; sets up appropriate
// code dependencies and might use the array protector cell.
......
......@@ -5431,16 +5431,11 @@ void BytecodeGenerator::BuildGetIterator(IteratorType hint) {
feedback_index(feedback_spec()->AddCallICSlot());
// Let method be GetMethod(obj, @@iterator) and
// iterator be Call(method, obj).
// iterator be Call(method, obj). If Type(iterator) is not Object,
// throw a SymbolIteratorInvalid exception.
builder()->StoreAccumulatorInRegister(obj).GetIterator(
obj, load_feedback_index, call_feedback_index);
}
// If Type(iterator) is not Object, throw a TypeError exception.
BytecodeLabel no_type_error;
builder()->JumpIfJSReceiver(&no_type_error);
builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
builder()->Bind(&no_type_error);
}
}
......
......@@ -3204,10 +3204,8 @@ IGNITION_HANDLER(ForInStep, InterpreterAssembler) {
// GetIterator <object>
//
// Retrieves the object[Symbol.iterator] method, calls it and stores
// the result in the accumulator
// TODO(swapnilgaikwad): Extend the functionality of the bytecode to
// check if the result is a JSReceiver else throw SymbolIteratorInvalid
// runtime exception
// the result in the accumulator. If the result is not a JSReceiver, throws
// SymbolIteratorInvalid runtime exception.
IGNITION_HANDLER(GetIterator, InterpreterAssembler) {
TNode<Object> receiver = LoadRegisterAtOperandIndex(0);
TNode<Context> context = GetContext();
......
......@@ -143,7 +143,7 @@ snippet: "
"
frame size: 6
parameter count: 1
bytecode array length: 75
bytecode array length: 68
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
......@@ -153,8 +153,6 @@ bytecodes: [
B(LdaConstant), U8(2),
/* 67 S> */ B(Star), R(1),
B(GetIterator), R(0), U8(2), U8(4),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(3), U8(6),
B(Star), R(3),
......
......@@ -214,7 +214,7 @@ snippet: "
"
frame size: 19
parameter count: 1
bytecode array length: 364
bytecode array length: 357
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4),
......@@ -239,8 +239,6 @@ bytecodes: [
/* 36 S> */ B(CreateArrayLiteral), U8(4), U8(0), U8(37),
B(Star), R(10),
B(GetIterator), R(10), U8(1), U8(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(9),
B(LdaNamedProperty), R(9), U8(5), U8(5),
B(Star), R(8),
......@@ -374,7 +372,7 @@ bytecodes: [
]
constant pool: [
Smi [30],
Smi [143],
Smi [136],
Smi [16],
Smi [7],
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
......@@ -388,16 +386,16 @@ constant pool: [
Smi [6],
Smi [9],
SCOPE_INFO_TYPE,
Smi [269],
Smi [262],
Smi [6],
Smi [9],
Smi [23],
]
handlers: [
[20, 310, 318],
[23, 274, 276],
[87, 174, 182],
[206, 239, 241],
[20, 303, 311],
[23, 267, 269],
[80, 167, 175],
[199, 232, 234],
]
---
......
......@@ -67,7 +67,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 101
bytecode array length: 94
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaGlobal), U8(0), U8(0),
......@@ -81,11 +81,9 @@ bytecodes: [
/* 49 S> */ B(CreateArrayLiteral), U8(4), U8(5), U8(37),
B(Star), R(7),
B(GetIterator), R(7), U8(6), U8(8),
B(Mov), R(0), R(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(6),
B(LdaNamedProperty), R(6), U8(5), U8(10),
B(Mov), R(0), R(2),
B(Star), R(5),
B(CallProperty0), R(5), R(6), U8(19),
B(Star), R(7),
......
......@@ -12,19 +12,17 @@ snippet: "
"
frame size: 14
parameter count: 1
bytecode array length: 167
bytecode array length: 160
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(1),
/* 60 S> */ B(GetIterator), R(1), U8(1), U8(3),
B(Mov), R(1), R(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(1), U8(5),
B(Star), R(3),
B(LdaFalse),
B(Mov), R(1), R(2),
B(Star), R(5),
B(Mov), R(context), R(8),
/* 57 S> */ B(Ldar), R(5),
......@@ -99,8 +97,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[35, 77, 85],
[109, 142, 144],
[28, 70, 78],
[102, 135, 137],
]
---
......@@ -110,19 +108,17 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 253
bytecode array length: 246
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(2),
/* 69 S> */ B(GetIterator), R(2), U8(1), U8(3),
B(Mov), R(2), R(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(1), U8(5),
B(Star), R(4),
B(LdaFalse),
B(Mov), R(2), R(3),
B(Star), R(6),
B(Mov), R(context), R(9),
B(Ldar), R(6),
......@@ -231,8 +227,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[35, 163, 171],
[195, 228, 230],
[28, 156, 164],
[188, 221, 223],
]
---
......@@ -242,7 +238,7 @@ snippet: "
"
frame size: 16
parameter count: 1
bytecode array length: 218
bytecode array length: 211
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 40 S> */ B(CreateEmptyObjectLiteral),
......@@ -250,13 +246,11 @@ bytecodes: [
/* 51 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(2),
/* 68 S> */ B(GetIterator), R(2), U8(1), U8(3),
B(Mov), R(2), R(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(1), U8(5),
B(Star), R(4),
B(LdaFalse),
B(Mov), R(2), R(3),
B(Star), R(6),
B(Mov), R(context), R(9),
/* 59 S> */ B(Ldar), R(6),
......@@ -351,8 +345,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[38, 128, 136],
[160, 193, 195],
[31, 121, 129],
[153, 186, 188],
]
---
......
......@@ -532,7 +532,7 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 253
bytecode array length: 246
bytecodes: [
B(Mov), R(closure), R(2),
B(Mov), R(this), R(3),
......@@ -545,8 +545,6 @@ bytecodes: [
/* 68 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(5),
B(GetIterator), R(5), U8(2), U8(4),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(2), U8(6),
B(Star), R(3),
......@@ -658,8 +656,8 @@ constant pool: [
SCOPE_INFO_TYPE,
]
handlers: [
[16, 225, 225],
[53, 106, 114],
[138, 171, 173],
[16, 218, 218],
[46, 99, 107],
[131, 164, 166],
]
......@@ -11,14 +11,12 @@ snippet: "
"
frame size: 13
parameter count: 1
bytecode array length: 165
bytecode array length: 158
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(4),
B(GetIterator), R(4), U8(1), U8(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(1), U8(5),
B(Star), R(2),
......@@ -96,8 +94,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[32, 75, 83],
[107, 140, 142],
[25, 68, 76],
[100, 133, 135],
]
---
......@@ -107,14 +105,12 @@ snippet: "
"
frame size: 14
parameter count: 1
bytecode array length: 173
bytecode array length: 166
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
B(Star), R(0),
/* 68 S> */ B(GetIterator), R(0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(4),
B(LdaNamedProperty), R(4), U8(1), U8(4),
B(Star), R(3),
......@@ -198,8 +194,8 @@ constant pool: [
Smi [9],
]
handlers: [
[30, 77, 85],
[109, 142, 144],
[23, 70, 78],
[102, 135, 137],
]
---
......@@ -211,14 +207,12 @@ snippet: "
"
frame size: 13
parameter count: 1
bytecode array length: 181
bytecode array length: 174
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(4),
B(GetIterator), R(4), U8(1), U8(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(1), U8(5),
B(Star), R(2),
......@@ -303,8 +297,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[32, 91, 99],
[123, 156, 158],
[25, 84, 92],
[116, 149, 151],
]
---
......@@ -314,7 +308,7 @@ snippet: "
"
frame size: 13
parameter count: 1
bytecode array length: 187
bytecode array length: 180
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41),
......@@ -322,8 +316,6 @@ bytecodes: [
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(37),
B(Star), R(3),
B(GetIterator), R(3), U8(2), U8(4),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(2),
B(LdaNamedProperty), R(2), U8(2), U8(6),
B(Star), R(1),
......@@ -411,7 +403,7 @@ constant pool: [
Smi [9],
]
handlers: [
[38, 91, 99],
[123, 156, 158],
[31, 84, 92],
[116, 149, 151],
]
......@@ -15,12 +15,10 @@ snippet: "
"
frame size: 15
parameter count: 2
bytecode array length: 162
bytecode array length: 155
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 34 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(0), U8(4),
B(Star), R(4),
......@@ -98,8 +96,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[26, 72, 80],
[104, 137, 139],
[19, 65, 73],
[97, 130, 132],
]
---
......@@ -111,7 +109,7 @@ snippet: "
"
frame size: 20
parameter count: 2
bytecode array length: 246
bytecode array length: 239
bytecodes: [
B(CreateFunctionContext), U8(0), U8(4),
B(PushContext), R(2),
......@@ -131,8 +129,6 @@ bytecodes: [
/* 34 S> */ B(LdaContextSlot), R(3), U8(4), U8(0),
B(Star), R(6),
B(GetIterator), R(6), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(2), U8(4),
B(Star), R(4),
......@@ -237,8 +233,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[59, 154, 162],
[186, 219, 221],
[52, 147, 155],
[179, 212, 214],
]
---
......@@ -250,12 +246,10 @@ snippet: "
"
frame size: 14
parameter count: 2
bytecode array length: 179
bytecode array length: 172
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 34 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(0), U8(4),
B(Star), R(2),
......@@ -343,8 +337,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[26, 89, 97],
[121, 154, 156],
[19, 82, 90],
[114, 147, 149],
]
---
......@@ -356,12 +350,10 @@ snippet: "
"
frame size: 17
parameter count: 2
bytecode array length: 173
bytecode array length: 166
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 41 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(7),
B(LdaNamedProperty), R(7), U8(0), U8(4),
B(Star), R(6),
......@@ -445,8 +437,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[26, 83, 91],
[115, 148, 150],
[19, 76, 84],
[108, 141, 143],
]
---
......@@ -458,7 +450,7 @@ snippet: "
"
frame size: 16
parameter count: 2
bytecode array length: 203
bytecode array length: 196
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(1),
B(Mov), R(closure), R(5),
......@@ -476,8 +468,6 @@ bytecodes: [
B(Ldar), R(5),
/* 55 S> */ B(Return),
/* 35 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(6),
B(LdaNamedProperty), R(6), U8(3), U8(4),
B(Star), R(5),
......@@ -558,8 +548,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
]
handlers: [
[67, 113, 121],
[145, 178, 180],
[60, 106, 114],
[138, 171, 173],
]
---
......@@ -571,7 +561,7 @@ snippet: "
"
frame size: 15
parameter count: 2
bytecode array length: 247
bytecode array length: 240
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4),
......@@ -589,8 +579,6 @@ bytecodes: [
B(Ldar), R(4),
/* 49 S> */ B(Return),
/* 35 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(4), U8(4),
B(Star), R(4),
......@@ -678,7 +666,7 @@ bytecodes: [
]
constant pool: [
Smi [22],
Smi [120],
Smi [113],
Smi [10],
Smi [7],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
......@@ -692,8 +680,8 @@ constant pool: [
Smi [9],
]
handlers: [
[67, 151, 159],
[183, 216, 218],
[60, 144, 152],
[176, 209, 211],
]
---
......@@ -705,7 +693,7 @@ snippet: "
"
frame size: 17
parameter count: 2
bytecode array length: 217
bytecode array length: 210
bytecodes: [
B(Mov), R(closure), R(5),
B(Mov), R(this), R(6),
......@@ -714,8 +702,6 @@ bytecodes: [
/* 16 E> */ B(StackCheck),
B(Mov), R(context), R(5),
/* 40 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(7),
B(LdaNamedProperty), R(7), U8(0), U8(4),
B(Star), R(6),
......@@ -813,9 +799,9 @@ constant pool: [
SCOPE_INFO_TYPE,
]
handlers: [
[16, 189, 189],
[41, 87, 95],
[119, 152, 154],
[16, 182, 182],
[34, 80, 88],
[112, 145, 147],
]
---
......@@ -827,7 +813,7 @@ snippet: "
"
frame size: 16
parameter count: 2
bytecode array length: 253
bytecode array length: 246
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(1),
B(Mov), R(closure), R(4),
......@@ -837,8 +823,6 @@ bytecodes: [
/* 16 E> */ B(StackCheck),
B(Mov), R(context), R(4),
/* 40 S> */ B(GetIterator), R(arg0), U8(0), U8(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(6),
B(LdaNamedProperty), R(6), U8(1), U8(4),
B(Star), R(5),
......@@ -940,7 +924,7 @@ bytecodes: [
/* 54 S> */ B(Return),
]
constant pool: [
Smi [98],
Smi [91],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
......@@ -949,8 +933,8 @@ constant pool: [
SCOPE_INFO_TYPE,
]
handlers: [
[20, 225, 225],
[45, 123, 131],
[155, 188, 190],
[20, 218, 218],
[38, 116, 124],
[148, 181, 183],
]
......@@ -100,7 +100,7 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 253
bytecode array length: 246
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4),
......@@ -120,8 +120,6 @@ bytecodes: [
/* 30 S> */ B(CreateArrayLiteral), U8(4), U8(0), U8(37),
B(Star), R(6),
B(GetIterator), R(6), U8(1), U8(3),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(5),
B(LdaNamedProperty), R(5), U8(5), U8(5),
B(Star), R(4),
......@@ -209,7 +207,7 @@ bytecodes: [
]
constant pool: [
Smi [22],
Smi [126],
Smi [119],
Smi [10],
Smi [7],
ARRAY_BOILERPLATE_DESCRIPTION_TYPE,
......@@ -224,8 +222,8 @@ constant pool: [
Smi [9],
]
handlers: [
[73, 157, 165],
[189, 222, 224],
[66, 150, 158],
[182, 215, 217],
]
---
......@@ -236,7 +234,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 205
bytecode array length: 198
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(1),
......@@ -258,8 +256,6 @@ bytecodes: [
/* 50 E> */ B(CallUndefinedReceiver0), R(5), U8(2),
B(Star), R(6),
B(GetIterator), R(6), U8(4), U8(6),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(3),
B(LdaNamedProperty), R(3), U8(5), U8(8),
B(Star), R(5),
......@@ -316,7 +312,7 @@ bytecodes: [
]
constant pool: [
Smi [22],
Smi [173],
Smi [166],
Smi [10],
Smi [7],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["g"],
......
......@@ -94,7 +94,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 125
bytecode array length: 118
bytecodes: [
/* 30 E> */ B(StackCheck),
B(CreateBlockContext), U8(0),
......@@ -118,12 +118,10 @@ bytecodes: [
/* 101 S> */ B(CreateArrayLiteral), U8(5), U8(1), U8(37),
B(Star), R(7),
B(GetIterator), R(7), U8(2), U8(4),
B(Mov), R(5), R(2),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(6),
B(LdaNamedProperty), R(6), U8(6), U8(6),
B(Star), R(5),
B(Mov), R(1), R(2),
B(CallProperty0), R(5), R(6), U8(15),
B(Star), R(7),
B(JumpIfJSReceiver), U8(7),
......
......@@ -93,7 +93,7 @@ snippet: "
"
frame size: 11
parameter count: 1
bytecode array length: 119
bytecode array length: 112
bytecodes: [
B(CreateRestParameter),
B(Star), R(3),
......@@ -112,12 +112,10 @@ bytecodes: [
B(Inc), U8(3),
/* 152 S> */ B(Star), R(6),
B(GetIterator), R(3), U8(4), U8(6),
B(Mov), R(1), R(4),
B(JumpIfJSReceiver), U8(7),
B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0),
B(Star), R(9),
B(LdaNamedProperty), R(9), U8(0), U8(8),
B(Star), R(8),
B(Mov), R(1), R(4),
B(CallProperty0), R(8), R(9), U8(14),
B(Star), R(10),
B(JumpIfJSReceiver), U8(7),
......
......@@ -17,9 +17,10 @@ var iteratorAfterEagerDeoptCount = 0;
function foo(obj) {
// The following for-of loop uses the iterator protocol to iterate
// over the 'obj'.
// The GetIterator bytecode invovlves 2 steps:
// The GetIterator bytecode invovlves 3 steps:
// 1. method = GetMethod(obj, @@iterator)
// 2. iterator = Call(method, obj).
// 2. iterator = Call(method, obj)
// 3. if(!IsJSReceiver(iterator)) throw SymbolIteratorInvalid.
for(var x of obj){}
}
......
// Copyright 2019 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.
// The GetIterator bytecode is used to implement a part of the iterator
// protocol (https://tc39.es/ecma262/#sec-getiterator).
// Here, call to the @@iterator property returns invalid JS receiver.
// This test ensures that the optimized version of the GetIterator bytecode
// incorporates exception handling mechanism without deoptimizing.
// Flags: --allow-natives-syntax --opt
var iteratorCount = 0;
var exceptionCount = 0;
function foo(obj) {
// The following for-of loop uses the iterator protocol to iterate
// over the 'obj'.
// The GetIterator bytecode invovlves 3 steps:
// 1. method = GetMethod(obj, @@iterator)
// 2. iterator = Call(method, obj)
// 3. if(!IsJSReceiver(iterator)) throw SymbolIteratorInvalid.
try{
for(let a of obj){
assertUnreachable();
}
} catch(e){
exceptionCount++;
}
}
// This iterator retuns '3' which is not a valid JSReceiver
var iterator = function() {
iteratorCount++;
return 3;
}
let y = {
get [Symbol.iterator]() {
return iterator;
}
};
%PrepareFunctionForOptimization(foo);
foo(y);
foo(y);
%OptimizeFunctionOnNextCall(foo);
foo(y);
assertOptimized(foo);
assertEquals(iteratorCount, 3);
assertEquals(exceptionCount, 3);
......@@ -18,9 +18,10 @@ var getIteratorCount = 0;
function foo(obj) {
// The following for-of loop uses the iterator protocol to iterate
// over the 'obj'.
// The GetIterator bytecode invovlves 2 steps:
// The GetIterator bytecode invovlves 3 steps:
// 1. method = GetMethod(obj, @@iterator)
// 2. iterator = Call(method, obj).
// 2. iterator = Call(method, obj)
// 3. if(!IsJSReceiver(iterator)) throw SymbolIteratorInvalid.
for(var x of obj){}
}
......
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