OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/wasm/wasm-objects.h" | 5 #include "src/wasm/wasm-objects.h" |
6 #include "src/utils.h" | 6 #include "src/utils.h" |
7 | 7 |
| 8 #include "src/assembler-inl.h" |
8 #include "src/base/iterator.h" | 9 #include "src/base/iterator.h" |
| 10 #include "src/compiler/wasm-compiler.h" |
9 #include "src/debug/debug-interface.h" | 11 #include "src/debug/debug-interface.h" |
10 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
11 #include "src/wasm/module-decoder.h" | 13 #include "src/wasm/module-decoder.h" |
| 14 #include "src/wasm/wasm-code-specialization.h" |
12 #include "src/wasm/wasm-module.h" | 15 #include "src/wasm/wasm-module.h" |
13 #include "src/wasm/wasm-text.h" | 16 #include "src/wasm/wasm-text.h" |
14 | 17 |
15 #define TRACE(...) \ | 18 #define TRACE(...) \ |
16 do { \ | 19 do { \ |
17 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ | 20 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ |
18 } while (false) | 21 } while (false) |
19 | 22 |
20 #define TRACE_CHAIN(instance) \ | 23 #define TRACE_CHAIN(instance) \ |
21 do { \ | 24 do { \ |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 module_start + func.code_end_offset, &locals); | 210 module_start + func.code_end_offset, &locals); |
208 DCHECK_LT(0, locals.encoded_size); | 211 DCHECK_LT(0, locals.encoded_size); |
209 for (uint32_t offset : iterator.offsets()) { | 212 for (uint32_t offset : iterator.offsets()) { |
210 if (offset > static_cast<uint32_t>(offset_in_func)) break; | 213 if (offset > static_cast<uint32_t>(offset_in_func)) break; |
211 if (offset == static_cast<uint32_t>(offset_in_func)) return true; | 214 if (offset == static_cast<uint32_t>(offset_in_func)) return true; |
212 } | 215 } |
213 return false; | 216 return false; |
214 } | 217 } |
215 #endif // DEBUG | 218 #endif // DEBUG |
216 | 219 |
| 220 int AdvanceSourcePositionTableIterator(SourcePositionTableIterator& iterator, |
| 221 int offset) { |
| 222 DCHECK(!iterator.done()); |
| 223 int byte_pos; |
| 224 do { |
| 225 byte_pos = iterator.source_position().ScriptOffset(); |
| 226 iterator.Advance(); |
| 227 } while (!iterator.done() && iterator.code_offset() <= offset); |
| 228 return byte_pos; |
| 229 } |
| 230 |
| 231 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { |
| 232 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
| 233 decoder.Reset(pc + 1, pc + 6); |
| 234 uint32_t call_idx = decoder.consume_u32v("call index"); |
| 235 DCHECK(decoder.ok()); |
| 236 DCHECK_GE(kMaxInt, call_idx); |
| 237 return static_cast<int>(call_idx); |
| 238 } |
| 239 |
| 240 static void RecordLazyCodeStats(Isolate* isolate, Code* code) { |
| 241 isolate->counters()->asm_wasm_lazily_compiled_functions()->Increment(); |
| 242 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); |
| 243 isolate->counters()->wasm_reloc_size()->Increment( |
| 244 code->relocation_info()->length()); |
| 245 } |
| 246 |
| 247 class LazyCompilationOrchestrator { |
| 248 bool CompileFunction(Isolate* isolate, Handle<WasmInstanceObject> instance, |
| 249 int func_index) WARN_UNUSED_RESULT { |
| 250 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
| 251 isolate); |
| 252 if (Code::cast(compiled_module->code_table()->get(func_index))->kind() == |
| 253 Code::WASM_FUNCTION) { |
| 254 return true; |
| 255 } |
| 256 wasm::ModuleEnv module_env(compiled_module->module(), nullptr); |
| 257 // TODO(clemensh): Remove this; it's not concurrency-safe. |
| 258 std::vector<Handle<FixedArray>> fun_tables; |
| 259 std::vector<Handle<FixedArray>> sig_tables; |
| 260 size_t num_function_tables = |
| 261 compiled_module->module()->function_tables.size(); |
| 262 for (size_t i = 0; i < num_function_tables; ++i) { |
| 263 fun_tables.push_back(isolate->factory()->NewFixedArray(1)); |
| 264 sig_tables.push_back(isolate->factory()->NewFixedArray(1)); |
| 265 } |
| 266 module_env.function_tables = &fun_tables; |
| 267 module_env.signature_tables = &sig_tables; |
| 268 uint8_t* module_start = compiled_module->module_bytes()->GetChars(); |
| 269 const WasmFunction* func = &module_env.module->functions[func_index]; |
| 270 wasm::FunctionBody body{func->sig, module_start, |
| 271 module_start + func->code_start_offset, |
| 272 module_start + func->code_end_offset}; |
| 273 wasm::WasmName name = Vector<const char>::cast( |
| 274 compiled_module->GetRawFunctionName(func_index)); |
| 275 ErrorThrower thrower(isolate, "WasmLazyCompile"); |
| 276 compiler::WasmCompilationUnit unit(isolate, &module_env, body, name, |
| 277 func_index); |
| 278 unit.ExecuteCompilation(); |
| 279 Handle<Code> code = unit.FinishCompilation(&thrower); |
| 280 |
| 281 Handle<FixedArray> deopt_data = |
| 282 isolate->factory()->NewFixedArray(2, TENURED); |
| 283 Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance); |
| 284 deopt_data->set(0, *weak_instance); |
| 285 deopt_data->set(1, Smi::FromInt(func_index)); |
| 286 code->set_deoptimization_data(*deopt_data); |
| 287 |
| 288 if (thrower.error()) { |
| 289 if (!isolate->has_pending_exception()) isolate->Throw(*thrower.Reify()); |
| 290 return false; |
| 291 } |
| 292 |
| 293 DCHECK_EQ(Builtins::kWasmCompileLazy, |
| 294 Code::cast(compiled_module->code_table()->get(func_index)) |
| 295 ->builtin_index()); |
| 296 compiled_module->code_table()->set(func_index, *code); |
| 297 |
| 298 // Now specialize the generated code for this instance. |
| 299 Zone specialization_zone(isolate->allocator(), ZONE_NAME); |
| 300 CodeSpecialization code_specialization(isolate, &specialization_zone); |
| 301 if (module_env.module->globals_size) { |
| 302 Address globals_start = reinterpret_cast<Address>( |
| 303 instance->globals_buffer()->backing_store()); |
| 304 code_specialization.RelocateGlobals(nullptr, globals_start); |
| 305 } |
| 306 if (instance->has_memory_buffer()) { |
| 307 Address mem_start = |
| 308 reinterpret_cast<Address>(instance->memory_buffer()->backing_store()); |
| 309 int mem_size = instance->memory_buffer()->byte_length()->Number(); |
| 310 DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr); |
| 311 if (mem_size > 0) { |
| 312 code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start, |
| 313 mem_size); |
| 314 } |
| 315 } |
| 316 code_specialization.RelocateDirectCalls(instance); |
| 317 if (module_env.used_indirect_tables) { |
| 318 for (size_t i = 0; i < num_function_tables; ++i) { |
| 319 Handle<Object> new_fun_table( |
| 320 compiled_module->function_tables()->get(static_cast<int>(i)), |
| 321 isolate); |
| 322 code_specialization.RelocateObject(fun_tables[i], new_fun_table); |
| 323 Handle<Object> new_sig_table( |
| 324 compiled_module->signature_tables()->get(static_cast<int>(i)), |
| 325 isolate); |
| 326 code_specialization.RelocateObject(sig_tables[i], new_sig_table); |
| 327 } |
| 328 } |
| 329 code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH); |
| 330 Assembler::FlushICache(isolate, code->instruction_start(), |
| 331 code->instruction_size()); |
| 332 RecordLazyCodeStats(isolate, *code); |
| 333 return true; |
| 334 } |
| 335 |
| 336 public: |
| 337 MaybeHandle<Code> CompileLazy(Isolate* isolate, |
| 338 Handle<WasmInstanceObject> instance, |
| 339 Handle<Code> caller, int call_offset, |
| 340 int exported_func_index, bool patch_caller) { |
| 341 struct NonCompiledFunction { |
| 342 int offset; |
| 343 int func_index; |
| 344 }; |
| 345 std::vector<NonCompiledFunction> non_compiled_functions; |
| 346 int func_to_return_idx = exported_func_index; |
| 347 wasm::Decoder decoder(nullptr, nullptr); |
| 348 bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION; |
| 349 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
| 350 isolate); |
| 351 |
| 352 if (is_js_to_wasm) { |
| 353 non_compiled_functions.push_back({0, exported_func_index}); |
| 354 } else if (patch_caller) { |
| 355 DisallowHeapAllocation no_gc; |
| 356 SeqOneByteString* module_bytes = compiled_module->module_bytes(); |
| 357 SourcePositionTableIterator source_pos_iterator( |
| 358 caller->source_position_table()); |
| 359 DCHECK_EQ(2, caller->deoptimization_data()->length()); |
| 360 int caller_func_index = |
| 361 Smi::cast(caller->deoptimization_data()->get(1))->value(); |
| 362 const byte* func_bytes = |
| 363 module_bytes->GetChars() + compiled_module->module() |
| 364 ->functions[caller_func_index] |
| 365 .code_start_offset; |
| 366 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); |
| 367 it.next()) { |
| 368 Code* callee = |
| 369 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 370 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; |
| 371 size_t offset_l = it.rinfo()->pc() - caller->instruction_start(); |
| 372 DCHECK_GE(kMaxInt, offset_l); |
| 373 int offset = static_cast<int>(offset_l); |
| 374 int byte_pos = |
| 375 AdvanceSourcePositionTableIterator(source_pos_iterator, offset); |
| 376 int called_func_index = |
| 377 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); |
| 378 non_compiled_functions.push_back({offset, called_func_index}); |
| 379 // Call offset one instruction after the call. Remember the last called |
| 380 // function before that offset. |
| 381 if (offset < call_offset) func_to_return_idx = called_func_index; |
| 382 } |
| 383 } |
| 384 |
| 385 // TODO(clemensh): compile all functions in non_compiled_functions in |
| 386 // background, wait for func_to_return_idx. |
| 387 if (!CompileFunction(isolate, instance, func_to_return_idx)) { |
| 388 return {}; |
| 389 } |
| 390 |
| 391 if (is_js_to_wasm || patch_caller) { |
| 392 DisallowHeapAllocation no_gc; |
| 393 // Now patch the code object with all functions which are now compiled. |
| 394 int idx = 0; |
| 395 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); |
| 396 it.next()) { |
| 397 Code* callee = |
| 398 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 399 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; |
| 400 DCHECK_GT(non_compiled_functions.size(), idx); |
| 401 int called_func_index = non_compiled_functions[idx].func_index; |
| 402 if (callee->deoptimization_data()->length() > 0) { |
| 403 DCHECK_EQ(called_func_index, |
| 404 Smi::cast(callee->deoptimization_data()->get(1))->value()); |
| 405 } |
| 406 if (is_js_to_wasm) { |
| 407 DCHECK_EQ(func_to_return_idx, called_func_index); |
| 408 } else { |
| 409 DCHECK_EQ(non_compiled_functions[idx].offset, |
| 410 it.rinfo()->pc() - caller->instruction_start()); |
| 411 } |
| 412 ++idx; |
| 413 Handle<Code> callee_compiled( |
| 414 Code::cast(compiled_module->code_table()->get(called_func_index))); |
| 415 if (callee_compiled->builtin_index() == Builtins::kWasmCompileLazy) { |
| 416 DCHECK_NE(func_to_return_idx, called_func_index); |
| 417 continue; |
| 418 } |
| 419 DCHECK_EQ(Code::WASM_FUNCTION, callee_compiled->kind()); |
| 420 it.rinfo()->set_target_address(callee_compiled->instruction_start()); |
| 421 } |
| 422 DCHECK_EQ(non_compiled_functions.size(), idx); |
| 423 } |
| 424 |
| 425 Code* ret = |
| 426 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); |
| 427 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); |
| 428 return handle(ret, isolate); |
| 429 } |
| 430 }; |
| 431 |
217 } // namespace | 432 } // namespace |
218 | 433 |
219 Handle<WasmModuleObject> WasmModuleObject::New( | 434 Handle<WasmModuleObject> WasmModuleObject::New( |
220 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { | 435 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { |
221 ModuleOrigin origin = compiled_module->module()->origin; | 436 ModuleOrigin origin = compiled_module->module()->origin; |
222 | 437 |
223 Handle<JSObject> module_object; | 438 Handle<JSObject> module_object; |
224 if (origin == ModuleOrigin::kWasmOrigin) { | 439 if (origin == ModuleOrigin::kWasmOrigin) { |
225 Handle<JSFunction> module_cons( | 440 Handle<JSFunction> module_cons( |
226 isolate->native_context()->wasm_module_constructor()); | 441 isolate->native_context()->wasm_module_constructor()); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 Foreign::cast(get(kModuleWrapper))->foreign_address())); | 755 Foreign::cast(get(kModuleWrapper))->foreign_address())); |
541 } | 756 } |
542 | 757 |
543 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, module_bytes, kModuleBytes, | 758 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, module_bytes, kModuleBytes, |
544 SeqOneByteString); | 759 SeqOneByteString); |
545 DEFINE_ARR_GETTER(WasmSharedModuleData, script, kScript, Script); | 760 DEFINE_ARR_GETTER(WasmSharedModuleData, script, kScript, Script); |
546 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, asm_js_offset_table, | 761 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, asm_js_offset_table, |
547 kAsmJsOffsetTable, ByteArray); | 762 kAsmJsOffsetTable, ByteArray); |
548 DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, breakpoint_infos, | 763 DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, breakpoint_infos, |
549 kBreakPointInfos, FixedArray); | 764 kBreakPointInfos, FixedArray); |
| 765 DEFINE_OPTIONAL_ARR_GETTER(WasmSharedModuleData, lazy_compilation_orchestrator, |
| 766 kLazyCompilationOrchestrator, Foreign); |
550 | 767 |
551 Handle<WasmSharedModuleData> WasmSharedModuleData::New( | 768 Handle<WasmSharedModuleData> WasmSharedModuleData::New( |
552 Isolate* isolate, Handle<Foreign> module_wrapper, | 769 Isolate* isolate, Handle<Foreign> module_wrapper, |
553 Handle<SeqOneByteString> module_bytes, Handle<Script> script, | 770 Handle<SeqOneByteString> module_bytes, Handle<Script> script, |
554 Handle<ByteArray> asm_js_offset_table) { | 771 Handle<ByteArray> asm_js_offset_table) { |
555 Handle<FixedArray> arr = | 772 Handle<FixedArray> arr = |
556 isolate->factory()->NewFixedArray(kFieldCount, TENURED); | 773 isolate->factory()->NewFixedArray(kFieldCount, TENURED); |
557 | 774 |
558 arr->set(kModuleWrapper, *module_wrapper); | 775 arr->set(kModuleWrapper, *module_wrapper); |
559 if (!module_bytes.is_null()) { | 776 if (!module_bytes.is_null()) { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 | 946 |
730 // Find the function for this breakpoint, and set the breakpoint. | 947 // Find the function for this breakpoint, and set the breakpoint. |
731 int func_index = compiled_module->GetContainingFunction(position); | 948 int func_index = compiled_module->GetContainingFunction(position); |
732 DCHECK_LE(0, func_index); | 949 DCHECK_LE(0, func_index); |
733 WasmFunction& func = compiled_module->module()->functions[func_index]; | 950 WasmFunction& func = compiled_module->module()->functions[func_index]; |
734 int offset_in_func = position - func.code_start_offset; | 951 int offset_in_func = position - func.code_start_offset; |
735 WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func); | 952 WasmDebugInfo::SetBreakpoint(debug_info, func_index, offset_in_func); |
736 } | 953 } |
737 } | 954 } |
738 | 955 |
| 956 void WasmSharedModuleData::PrepareForLazyCompilation( |
| 957 Handle<WasmSharedModuleData> shared) { |
| 958 if (shared->has_lazy_compilation_orchestrator()) return; |
| 959 Isolate* isolate = shared->GetIsolate(); |
| 960 LazyCompilationOrchestrator* orch = new LazyCompilationOrchestrator(); |
| 961 Handle<Managed<LazyCompilationOrchestrator>> orch_handle = |
| 962 Managed<LazyCompilationOrchestrator>::New(isolate, orch); |
| 963 shared->set(WasmSharedModuleData::kLazyCompilationOrchestrator, *orch_handle); |
| 964 } |
| 965 |
739 Handle<WasmCompiledModule> WasmCompiledModule::New( | 966 Handle<WasmCompiledModule> WasmCompiledModule::New( |
740 Isolate* isolate, Handle<WasmSharedModuleData> shared) { | 967 Isolate* isolate, Handle<WasmSharedModuleData> shared) { |
741 Handle<FixedArray> ret = | 968 Handle<FixedArray> ret = |
742 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); | 969 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); |
743 // WasmCompiledModule::cast would fail since fields are not set yet. | 970 // WasmCompiledModule::cast would fail since fields are not set yet. |
744 Handle<WasmCompiledModule> compiled_module( | 971 Handle<WasmCompiledModule> compiled_module( |
745 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); | 972 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); |
746 compiled_module->InitId(); | 973 compiled_module->InitId(); |
747 compiled_module->set_num_imported_functions(0); | 974 compiled_module->set_num_imported_functions(0); |
748 compiled_module->set_shared(shared); | 975 compiled_module->set_shared(shared); |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1155 if (maybe_breakpoint_info->IsUndefined(isolate)) return {}; | 1382 if (maybe_breakpoint_info->IsUndefined(isolate)) return {}; |
1156 Handle<BreakPointInfo> breakpoint_info = | 1383 Handle<BreakPointInfo> breakpoint_info = |
1157 Handle<BreakPointInfo>::cast(maybe_breakpoint_info); | 1384 Handle<BreakPointInfo>::cast(maybe_breakpoint_info); |
1158 if (breakpoint_info->source_position() != position) return {}; | 1385 if (breakpoint_info->source_position() != position) return {}; |
1159 | 1386 |
1160 Handle<Object> breakpoint_objects(breakpoint_info->break_point_objects(), | 1387 Handle<Object> breakpoint_objects(breakpoint_info->break_point_objects(), |
1161 isolate); | 1388 isolate); |
1162 return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects); | 1389 return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects); |
1163 } | 1390 } |
1164 | 1391 |
| 1392 MaybeHandle<Code> WasmCompiledModule::CompileLazy( |
| 1393 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, |
| 1394 int offset, int func_index, bool patch_caller) { |
| 1395 isolate->set_context(*instance->compiled_module()->native_context()); |
| 1396 Object* orch_obj = |
| 1397 instance->compiled_module()->shared()->lazy_compilation_orchestrator(); |
| 1398 LazyCompilationOrchestrator* orch = |
| 1399 Managed<LazyCompilationOrchestrator>::cast(orch_obj)->get(); |
| 1400 return orch->CompileLazy(isolate, instance, caller, offset, func_index, |
| 1401 patch_caller); |
| 1402 } |
| 1403 |
1165 Handle<WasmInstanceWrapper> WasmInstanceWrapper::New( | 1404 Handle<WasmInstanceWrapper> WasmInstanceWrapper::New( |
1166 Isolate* isolate, Handle<WasmInstanceObject> instance) { | 1405 Isolate* isolate, Handle<WasmInstanceObject> instance) { |
1167 Handle<FixedArray> array = | 1406 Handle<FixedArray> array = |
1168 isolate->factory()->NewFixedArray(kWrapperPropertyCount, TENURED); | 1407 isolate->factory()->NewFixedArray(kWrapperPropertyCount, TENURED); |
1169 Handle<WasmInstanceWrapper> instance_wrapper( | 1408 Handle<WasmInstanceWrapper> instance_wrapper( |
1170 reinterpret_cast<WasmInstanceWrapper*>(*array), isolate); | 1409 reinterpret_cast<WasmInstanceWrapper*>(*array), isolate); |
1171 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); | 1410 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); |
1172 instance_wrapper->set(kWrapperInstanceObject, *cell); | 1411 instance_wrapper->set(kWrapperInstanceObject, *cell); |
1173 return instance_wrapper; | 1412 return instance_wrapper; |
1174 } | 1413 } |
1175 | 1414 |
1176 bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) { | 1415 bool WasmInstanceWrapper::IsWasmInstanceWrapper(Object* obj) { |
1177 if (!obj->IsFixedArray()) return false; | 1416 if (!obj->IsFixedArray()) return false; |
1178 Handle<FixedArray> array = handle(FixedArray::cast(obj)); | 1417 Handle<FixedArray> array = handle(FixedArray::cast(obj)); |
1179 if (array->length() != kWrapperPropertyCount) return false; | 1418 if (array->length() != kWrapperPropertyCount) return false; |
1180 if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false; | 1419 if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false; |
1181 Isolate* isolate = array->GetIsolate(); | 1420 Isolate* isolate = array->GetIsolate(); |
1182 if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) && | 1421 if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) && |
1183 !array->get(kNextInstanceWrapper)->IsFixedArray()) | 1422 !array->get(kNextInstanceWrapper)->IsFixedArray()) |
1184 return false; | 1423 return false; |
1185 if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) && | 1424 if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) && |
1186 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) | 1425 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) |
1187 return false; | 1426 return false; |
1188 return true; | 1427 return true; |
1189 } | 1428 } |
OLD | NEW |