Created
November 15, 2016 00:25
-
-
Save tbodt/270ba1e82dc31faafa7802da4e7bcc5e to your computer and use it in GitHub Desktop.
how do i find a item in an array in javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Builtins::Generate_ArrayIndexOf(CodeStubAssembler* assembler) { | |
typedef compiler::Node Node; | |
typedef CodeStubAssembler::Label Label; | |
typedef CodeStubAssembler::Variable Variable; | |
Node* array = assembler->Parameter(0); | |
Node* search_element = assembler->Parameter(1); | |
Node* start_from = assembler->Parameter(2); | |
Node* context = assembler->Parameter(3 + 2); | |
Node* intptr_zero = assembler->IntPtrConstant(0); | |
Node* intptr_one = assembler->IntPtrConstant(1); | |
Node* undefined = assembler->UndefinedConstant(); | |
Node* heap_number_map = assembler->HeapNumberMapConstant(); | |
Variable len_var(assembler, MachineType::PointerRepresentation()), | |
index_var(assembler, MachineType::PointerRepresentation()), | |
start_from_var(assembler, MachineType::PointerRepresentation()); | |
Label init_k(assembler), return_found(assembler), return_not_found(assembler), | |
call_runtime(assembler); | |
Label init_len(assembler); | |
index_var.Bind(intptr_zero); | |
len_var.Bind(intptr_zero); | |
// Take slow path if not a JSArray, if retrieving elements requires | |
// traversing prototype, or if access checks are required. | |
assembler->BranchIfFastJSArray(array, context, &init_len, &call_runtime); | |
assembler->Bind(&init_len); | |
{ | |
// Handle case where JSArray length is not an Smi in the runtime | |
Node* len = assembler->LoadObjectField(array, JSArray::kLengthOffset); | |
assembler->GotoUnless(assembler->TaggedIsSmi(len), &call_runtime); | |
len_var.Bind(assembler->SmiToWord(len)); | |
assembler->Branch(assembler->WordEqual(len_var.value(), intptr_zero), | |
&return_not_found, &init_k); | |
} | |
assembler->Bind(&init_k); | |
{ | |
Label done(assembler), init_k_smi(assembler), init_k_heap_num(assembler), | |
init_k_zero(assembler), init_k_n(assembler); | |
Node* tagged_n = assembler->ToInteger(context, start_from); | |
assembler->Branch(assembler->TaggedIsSmi(tagged_n), &init_k_smi, | |
&init_k_heap_num); | |
assembler->Bind(&init_k_smi); | |
{ | |
start_from_var.Bind(assembler->SmiUntag(tagged_n)); | |
assembler->Goto(&init_k_n); | |
} | |
assembler->Bind(&init_k_heap_num); | |
{ | |
Label do_return_not_found(assembler); | |
// This round is lossless for all valid lengths. | |
Node* fp_len = assembler->RoundIntPtrToFloat64(len_var.value()); | |
Node* fp_n = assembler->LoadHeapNumberValue(tagged_n); | |
assembler->GotoIf(assembler->Float64GreaterThanOrEqual(fp_n, fp_len), | |
&do_return_not_found); | |
start_from_var.Bind(assembler->ChangeInt32ToIntPtr( | |
assembler->TruncateFloat64ToWord32(fp_n))); | |
assembler->Goto(&init_k_n); | |
assembler->Bind(&do_return_not_found); | |
{ | |
index_var.Bind(intptr_zero); | |
assembler->Goto(&return_not_found); | |
} | |
} | |
assembler->Bind(&init_k_n); | |
{ | |
Label if_positive(assembler), if_negative(assembler), done(assembler); | |
assembler->Branch( | |
assembler->IntPtrLessThan(start_from_var.value(), intptr_zero), | |
&if_negative, &if_positive); | |
assembler->Bind(&if_positive); | |
{ | |
index_var.Bind(start_from_var.value()); | |
assembler->Goto(&done); | |
} | |
assembler->Bind(&if_negative); | |
{ | |
index_var.Bind( | |
assembler->IntPtrAdd(len_var.value(), start_from_var.value())); | |
assembler->Branch( | |
assembler->IntPtrLessThan(index_var.value(), intptr_zero), | |
&init_k_zero, &done); | |
} | |
assembler->Bind(&init_k_zero); | |
{ | |
index_var.Bind(intptr_zero); | |
assembler->Goto(&done); | |
} | |
assembler->Bind(&done); | |
} | |
} | |
static int32_t kElementsKind[] = { | |
FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | |
FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, | |
}; | |
Label if_smiorobjects(assembler), if_packed_doubles(assembler), | |
if_holey_doubles(assembler); | |
Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, | |
&if_smiorobjects, &if_smiorobjects, | |
&if_packed_doubles, &if_holey_doubles}; | |
Node* map = assembler->LoadMap(array); | |
Node* elements_kind = assembler->LoadMapElementsKind(map); | |
Node* elements = assembler->LoadElements(array); | |
assembler->Switch(elements_kind, &return_not_found, kElementsKind, | |
element_kind_handlers, arraysize(kElementsKind)); | |
assembler->Bind(&if_smiorobjects); | |
{ | |
Variable search_num(assembler, MachineRepresentation::kFloat64); | |
Label ident_loop(assembler, &index_var), | |
heap_num_loop(assembler, &search_num), | |
string_loop(assembler, &index_var), simd_loop(assembler), | |
undef_loop(assembler, &index_var), not_smi(assembler), | |
not_heap_num(assembler); | |
assembler->GotoUnless(assembler->TaggedIsSmi(search_element), ¬_smi); | |
search_num.Bind(assembler->SmiToFloat64(search_element)); | |
assembler->Goto(&heap_num_loop); | |
assembler->Bind(¬_smi); | |
assembler->GotoIf(assembler->WordEqual(search_element, undefined), | |
&undef_loop); | |
Node* map = assembler->LoadMap(search_element); | |
assembler->GotoIf(assembler->WordNotEqual(map, heap_number_map), | |
¬_heap_num); | |
search_num.Bind(assembler->LoadHeapNumberValue(search_element)); | |
assembler->Goto(&heap_num_loop); | |
assembler->Bind(¬_heap_num); | |
Node* search_type = assembler->LoadMapInstanceType(map); | |
assembler->GotoIf(assembler->IsStringInstanceType(search_type), | |
&string_loop); | |
assembler->GotoIf( | |
assembler->Word32Equal(search_type, | |
assembler->Int32Constant(SIMD128_VALUE_TYPE)), | |
&simd_loop); | |
assembler->Goto(&ident_loop); | |
assembler->Bind(&ident_loop); | |
{ | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedArrayElement( | |
elements, index_var.value(), 0, CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->GotoIf(assembler->WordEqual(element_k, search_element), | |
&return_found); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(&ident_loop); | |
} | |
assembler->Bind(&undef_loop); | |
{ | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedArrayElement( | |
elements, index_var.value(), 0, CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->GotoIf(assembler->WordEqual(element_k, undefined), | |
&return_found); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(&undef_loop); | |
} | |
assembler->Bind(&heap_num_loop); | |
{ | |
Label not_nan_loop(assembler, &index_var); | |
assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
¬_nan_loop); | |
assembler->Bind(¬_nan_loop); | |
{ | |
Label continue_loop(assembler), not_smi(assembler); | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedArrayElement( | |
elements, index_var.value(), 0, | |
CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->GotoUnless(assembler->TaggedIsSmi(element_k), ¬_smi); | |
assembler->Branch( | |
assembler->Float64Equal(search_num.value(), | |
assembler->SmiToFloat64(element_k)), | |
&return_found, &continue_loop); | |
assembler->Bind(¬_smi); | |
assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k), | |
heap_number_map), | |
&continue_loop); | |
assembler->Branch( | |
assembler->Float64Equal(search_num.value(), | |
assembler->LoadHeapNumberValue(element_k)), | |
&return_found, &continue_loop); | |
assembler->Bind(&continue_loop); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(¬_nan_loop); | |
} | |
} | |
assembler->Bind(&string_loop); | |
{ | |
Label continue_loop(assembler); | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedArrayElement( | |
elements, index_var.value(), 0, CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->GotoIf(assembler->TaggedIsSmi(element_k), &continue_loop); | |
assembler->GotoUnless(assembler->IsStringInstanceType( | |
assembler->LoadInstanceType(element_k)), | |
&continue_loop); | |
// TODO(bmeurer): Consider inlining the StringEqual logic here. | |
Callable callable = CodeFactory::StringEqual(assembler->isolate()); | |
Node* result = | |
assembler->CallStub(callable, context, search_element, element_k); | |
assembler->Branch( | |
assembler->WordEqual(assembler->BooleanConstant(true), result), | |
&return_found, &continue_loop); | |
assembler->Bind(&continue_loop); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(&string_loop); | |
} | |
assembler->Bind(&simd_loop); | |
{ | |
Label continue_loop(assembler, &index_var), | |
loop_body(assembler, &index_var); | |
Node* map = assembler->LoadMap(search_element); | |
assembler->Goto(&loop_body); | |
assembler->Bind(&loop_body); | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedArrayElement( | |
elements, index_var.value(), 0, CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->GotoIf(assembler->TaggedIsSmi(element_k), &continue_loop); | |
Node* map_k = assembler->LoadMap(element_k); | |
assembler->BranchIfSimd128Equal(search_element, map, element_k, map_k, | |
&return_found, &continue_loop); | |
assembler->Bind(&continue_loop); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(&loop_body); | |
} | |
} | |
assembler->Bind(&if_packed_doubles); | |
{ | |
Label not_nan_loop(assembler, &index_var), search_notnan(assembler); | |
Variable search_num(assembler, MachineRepresentation::kFloat64); | |
assembler->GotoUnless(assembler->TaggedIsSmi(search_element), | |
&search_notnan); | |
search_num.Bind(assembler->SmiToFloat64(search_element)); | |
assembler->Goto(¬_nan_loop); | |
assembler->Bind(&search_notnan); | |
assembler->GotoIf(assembler->WordNotEqual( | |
assembler->LoadMap(search_element), heap_number_map), | |
&return_not_found); | |
search_num.Bind(assembler->LoadHeapNumberValue(search_element)); | |
assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
¬_nan_loop); | |
// Search for HeapNumber | |
assembler->Bind(¬_nan_loop); | |
{ | |
Label continue_loop(assembler); | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
Node* element_k = assembler->LoadFixedDoubleArrayElement( | |
elements, index_var.value(), MachineType::Float64(), 0, | |
CodeStubAssembler::INTPTR_PARAMETERS); | |
assembler->Branch(assembler->Float64Equal(element_k, search_num.value()), | |
&return_found, &continue_loop); | |
assembler->Bind(&continue_loop); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(¬_nan_loop); | |
} | |
} | |
assembler->Bind(&if_holey_doubles); | |
{ | |
Label not_nan_loop(assembler, &index_var), search_notnan(assembler); | |
Variable search_num(assembler, MachineRepresentation::kFloat64); | |
assembler->GotoUnless(assembler->TaggedIsSmi(search_element), | |
&search_notnan); | |
search_num.Bind(assembler->SmiToFloat64(search_element)); | |
assembler->Goto(¬_nan_loop); | |
assembler->Bind(&search_notnan); | |
assembler->GotoIf(assembler->WordNotEqual( | |
assembler->LoadMap(search_element), heap_number_map), | |
&return_not_found); | |
search_num.Bind(assembler->LoadHeapNumberValue(search_element)); | |
assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | |
¬_nan_loop); | |
// Search for HeapNumber | |
assembler->Bind(¬_nan_loop); | |
{ | |
Label continue_loop(assembler); | |
assembler->GotoUnless( | |
assembler->UintPtrLessThan(index_var.value(), len_var.value()), | |
&return_not_found); | |
// Load double value or continue if it contains a double hole. | |
Node* element_k = assembler->LoadFixedDoubleArrayElement( | |
elements, index_var.value(), MachineType::Float64(), 0, | |
CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | |
assembler->Branch(assembler->Float64Equal(element_k, search_num.value()), | |
&return_found, &continue_loop); | |
assembler->Bind(&continue_loop); | |
index_var.Bind(assembler->IntPtrAdd(index_var.value(), intptr_one)); | |
assembler->Goto(¬_nan_loop); | |
} | |
} | |
assembler->Bind(&return_found); | |
assembler->Return(assembler->ChangeInt32ToTagged(index_var.value())); | |
assembler->Bind(&return_not_found); | |
assembler->Return(assembler->NumberConstant(-1)); | |
assembler->Bind(&call_runtime); | |
assembler->Return(assembler->CallRuntime(Runtime::kArrayIndexOf, context, | |
array, search_element, start_from)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, v8 has 363 lines of code for
Array.prototype.indexOf
.