| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "serialize.h" | 34 #include "serialize.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 // ------------------------------------------------------------------------- | 39 // ------------------------------------------------------------------------- |
| 40 // MacroAssembler implementation. | 40 // MacroAssembler implementation. |
| 41 | 41 |
| 42 MacroAssembler::MacroAssembler(void* buffer, int size) | 42 MacroAssembler::MacroAssembler(void* buffer, int size) |
| 43 : Assembler(buffer, size), | 43 : Assembler(buffer, size), |
| 44 unresolved_(0), | |
| 45 generating_stub_(false), | 44 generating_stub_(false), |
| 46 allow_stub_calls_(true), | 45 allow_stub_calls_(true), |
| 47 code_object_(Heap::undefined_value()) { | 46 code_object_(Heap::undefined_value()) { |
| 48 } | 47 } |
| 49 | 48 |
| 50 | 49 |
| 51 static void RecordWriteHelper(MacroAssembler* masm, | 50 static void RecordWriteHelper(MacroAssembler* masm, |
| 52 Register object, | 51 Register object, |
| 53 Register addr, | 52 Register addr, |
| 54 Register scratch) { | 53 Register scratch) { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 int r = JSCallerSavedCode(i); | 300 int r = JSCallerSavedCode(i); |
| 302 if ((regs & (1 << r)) != 0) { | 301 if ((regs & (1 << r)) != 0) { |
| 303 mov(scratch, Operand(base, 0)); | 302 mov(scratch, Operand(base, 0)); |
| 304 ExternalReference reg_addr = | 303 ExternalReference reg_addr = |
| 305 ExternalReference(Debug_Address::Register(i)); | 304 ExternalReference(Debug_Address::Register(i)); |
| 306 mov(Operand::StaticVariable(reg_addr), scratch); | 305 mov(Operand::StaticVariable(reg_addr), scratch); |
| 307 lea(base, Operand(base, kPointerSize)); | 306 lea(base, Operand(base, kPointerSize)); |
| 308 } | 307 } |
| 309 } | 308 } |
| 310 } | 309 } |
| 310 |
| 311 void MacroAssembler::DebugBreak() { |
| 312 Set(eax, Immediate(0)); |
| 313 mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak))); |
| 314 CEntryStub ces(1); |
| 315 call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 316 } |
| 311 #endif | 317 #endif |
| 312 | 318 |
| 313 void MacroAssembler::Set(Register dst, const Immediate& x) { | 319 void MacroAssembler::Set(Register dst, const Immediate& x) { |
| 314 if (x.is_zero()) { | 320 if (x.is_zero()) { |
| 315 xor_(dst, Operand(dst)); // shorter than mov | 321 xor_(dst, Operand(dst)); // shorter than mov |
| 316 } else { | 322 } else { |
| 317 mov(dst, x); | 323 mov(dst, x); |
| 318 } | 324 } |
| 319 } | 325 } |
| 320 | 326 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 } else { | 376 } else { |
| 371 fucompp(); | 377 fucompp(); |
| 372 push(eax); | 378 push(eax); |
| 373 fnstsw_ax(); | 379 fnstsw_ax(); |
| 374 sahf(); | 380 sahf(); |
| 375 pop(eax); | 381 pop(eax); |
| 376 } | 382 } |
| 377 } | 383 } |
| 378 | 384 |
| 379 | 385 |
| 386 void MacroAssembler::AbortIfNotNumber(Register object, const char* msg) { |
| 387 Label ok; |
| 388 test(object, Immediate(kSmiTagMask)); |
| 389 j(zero, &ok); |
| 390 cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 391 Factory::heap_number_map()); |
| 392 Assert(equal, msg); |
| 393 bind(&ok); |
| 394 } |
| 395 |
| 396 |
| 380 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 397 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 381 push(ebp); | 398 push(ebp); |
| 382 mov(ebp, Operand(esp)); | 399 mov(ebp, Operand(esp)); |
| 383 push(esi); | 400 push(esi); |
| 384 push(Immediate(Smi::FromInt(type))); | 401 push(Immediate(Smi::FromInt(type))); |
| 385 push(Immediate(CodeObject())); | 402 push(Immediate(CodeObject())); |
| 386 if (FLAG_debug_code) { | 403 if (FLAG_debug_code) { |
| 387 cmp(Operand(esp, 0), Immediate(Factory::undefined_value())); | 404 cmp(Operand(esp, 0), Immediate(Factory::undefined_value())); |
| 388 Check(not_equal, "code object not properly patched"); | 405 Check(not_equal, "code object not properly patched"); |
| 389 } | 406 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 402 void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) { | 419 void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) { |
| 403 // Setup the frame structure on the stack. | 420 // Setup the frame structure on the stack. |
| 404 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 421 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
| 405 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 422 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
| 406 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); | 423 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); |
| 407 push(ebp); | 424 push(ebp); |
| 408 mov(ebp, Operand(esp)); | 425 mov(ebp, Operand(esp)); |
| 409 | 426 |
| 410 // Reserve room for entry stack pointer and push the debug marker. | 427 // Reserve room for entry stack pointer and push the debug marker. |
| 411 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 428 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
| 412 push(Immediate(0)); // saved entry sp, patched before call | 429 push(Immediate(0)); // Saved entry sp, patched before call. |
| 413 if (mode == ExitFrame::MODE_DEBUG) { | 430 push(Immediate(CodeObject())); // Accessed from ExitFrame::code_slot. |
| 414 push(Immediate(0)); | |
| 415 } else { | |
| 416 push(Immediate(CodeObject())); | |
| 417 } | |
| 418 | 431 |
| 419 // Save the frame pointer and the context in top. | 432 // Save the frame pointer and the context in top. |
| 420 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | 433 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); |
| 421 ExternalReference context_address(Top::k_context_address); | 434 ExternalReference context_address(Top::k_context_address); |
| 422 mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 435 mov(Operand::StaticVariable(c_entry_fp_address), ebp); |
| 423 mov(Operand::StaticVariable(context_address), esi); | 436 mov(Operand::StaticVariable(context_address), esi); |
| 424 } | 437 } |
| 425 | 438 |
| 426 void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) { | 439 void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) { |
| 427 #ifdef ENABLE_DEBUGGER_SUPPORT | 440 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 void MacroAssembler::PopTryHandler() { | 557 void MacroAssembler::PopTryHandler() { |
| 545 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 558 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
| 546 pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); | 559 pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); |
| 547 add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); | 560 add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); |
| 548 } | 561 } |
| 549 | 562 |
| 550 | 563 |
| 551 Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, | 564 Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg, |
| 552 JSObject* holder, Register holder_reg, | 565 JSObject* holder, Register holder_reg, |
| 553 Register scratch, | 566 Register scratch, |
| 567 int save_at_depth, |
| 554 Label* miss) { | 568 Label* miss) { |
| 555 // Make sure there's no overlap between scratch and the other | 569 // Make sure there's no overlap between scratch and the other |
| 556 // registers. | 570 // registers. |
| 557 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); | 571 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); |
| 558 | 572 |
| 559 // Keep track of the current object in register reg. | 573 // Keep track of the current object in register reg. |
| 560 Register reg = object_reg; | 574 Register reg = object_reg; |
| 561 int depth = 1; | 575 int depth = 0; |
| 576 |
| 577 if (save_at_depth == depth) { |
| 578 mov(Operand(esp, kPointerSize), object_reg); |
| 579 } |
| 562 | 580 |
| 563 // Check the maps in the prototype chain. | 581 // Check the maps in the prototype chain. |
| 564 // Traverse the prototype chain from the object and do map checks. | 582 // Traverse the prototype chain from the object and do map checks. |
| 565 while (object != holder) { | 583 while (object != holder) { |
| 566 depth++; | 584 depth++; |
| 567 | 585 |
| 568 // Only global objects and objects that do not require access | 586 // Only global objects and objects that do not require access |
| 569 // checks are allowed in stubs. | 587 // checks are allowed in stubs. |
| 570 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 588 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 571 | 589 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 583 CheckAccessGlobalProxy(reg, scratch, miss); | 601 CheckAccessGlobalProxy(reg, scratch, miss); |
| 584 | 602 |
| 585 // Restore scratch register to be the map of the object. | 603 // Restore scratch register to be the map of the object. |
| 586 // We load the prototype from the map in the scratch register. | 604 // We load the prototype from the map in the scratch register. |
| 587 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 605 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 588 } | 606 } |
| 589 // The prototype is in new space; we cannot store a reference | 607 // The prototype is in new space; we cannot store a reference |
| 590 // to it in the code. Load it from the map. | 608 // to it in the code. Load it from the map. |
| 591 reg = holder_reg; // from now the object is in holder_reg | 609 reg = holder_reg; // from now the object is in holder_reg |
| 592 mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 610 mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 593 | |
| 594 } else { | 611 } else { |
| 595 // Check the map of the current object. | 612 // Check the map of the current object. |
| 596 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 613 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 597 Immediate(Handle<Map>(object->map()))); | 614 Immediate(Handle<Map>(object->map()))); |
| 598 // Branch on the result of the map check. | 615 // Branch on the result of the map check. |
| 599 j(not_equal, miss, not_taken); | 616 j(not_equal, miss, not_taken); |
| 600 // Check access rights to the global object. This has to happen | 617 // Check access rights to the global object. This has to happen |
| 601 // after the map check so that we know that the object is | 618 // after the map check so that we know that the object is |
| 602 // actually a global object. | 619 // actually a global object. |
| 603 if (object->IsJSGlobalProxy()) { | 620 if (object->IsJSGlobalProxy()) { |
| 604 CheckAccessGlobalProxy(reg, scratch, miss); | 621 CheckAccessGlobalProxy(reg, scratch, miss); |
| 605 } | 622 } |
| 606 // The prototype is in old space; load it directly. | 623 // The prototype is in old space; load it directly. |
| 607 reg = holder_reg; // from now the object is in holder_reg | 624 reg = holder_reg; // from now the object is in holder_reg |
| 608 mov(reg, Handle<JSObject>(prototype)); | 625 mov(reg, Handle<JSObject>(prototype)); |
| 609 } | 626 } |
| 610 | 627 |
| 628 if (save_at_depth == depth) { |
| 629 mov(Operand(esp, kPointerSize), reg); |
| 630 } |
| 631 |
| 611 // Go to the next object in the prototype chain. | 632 // Go to the next object in the prototype chain. |
| 612 object = prototype; | 633 object = prototype; |
| 613 } | 634 } |
| 614 | 635 |
| 615 // Check the holder map. | 636 // Check the holder map. |
| 616 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 637 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 617 Immediate(Handle<Map>(holder->map()))); | 638 Immediate(Handle<Map>(holder->map()))); |
| 618 j(not_equal, miss, not_taken); | 639 j(not_equal, miss, not_taken); |
| 619 | 640 |
| 620 // Log the check depth. | 641 // Log the check depth. |
| 621 LOG(IntEvent("check-maps-depth", depth)); | 642 LOG(IntEvent("check-maps-depth", depth + 1)); |
| 622 | 643 |
| 623 // Perform security check for access to the global object and return | 644 // Perform security check for access to the global object and return |
| 624 // the holder register. | 645 // the holder register. |
| 625 ASSERT(object == holder); | 646 ASSERT(object == holder); |
| 626 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 647 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 627 if (object->IsJSGlobalProxy()) { | 648 if (object->IsJSGlobalProxy()) { |
| 628 CheckAccessGlobalProxy(reg, scratch, miss); | 649 CheckAccessGlobalProxy(reg, scratch, miss); |
| 629 } | 650 } |
| 630 return reg; | 651 return reg; |
| 631 } | 652 } |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 // arguments passed in because it is constant. At some point we | 1149 // arguments passed in because it is constant. At some point we |
| 1129 // should remove this need and make the runtime routine entry code | 1150 // should remove this need and make the runtime routine entry code |
| 1130 // smarter. | 1151 // smarter. |
| 1131 Set(eax, Immediate(num_arguments)); | 1152 Set(eax, Immediate(num_arguments)); |
| 1132 mov(ebx, Immediate(ExternalReference(f))); | 1153 mov(ebx, Immediate(ExternalReference(f))); |
| 1133 CEntryStub ces(1); | 1154 CEntryStub ces(1); |
| 1134 CallStub(&ces); | 1155 CallStub(&ces); |
| 1135 } | 1156 } |
| 1136 | 1157 |
| 1137 | 1158 |
| 1159 void MacroAssembler::CallExternalReference(ExternalReference ref, |
| 1160 int num_arguments) { |
| 1161 mov(eax, Immediate(num_arguments)); |
| 1162 mov(ebx, Immediate(ref)); |
| 1163 |
| 1164 CEntryStub stub(1); |
| 1165 CallStub(&stub); |
| 1166 } |
| 1167 |
| 1168 |
| 1138 Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, | 1169 Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, |
| 1139 int num_arguments) { | 1170 int num_arguments) { |
| 1140 if (f->nargs >= 0 && f->nargs != num_arguments) { | 1171 if (f->nargs >= 0 && f->nargs != num_arguments) { |
| 1141 IllegalOperation(num_arguments); | 1172 IllegalOperation(num_arguments); |
| 1142 // Since we did not call the stub, there was no allocation failure. | 1173 // Since we did not call the stub, there was no allocation failure. |
| 1143 // Return some non-failure object. | 1174 // Return some non-failure object. |
| 1144 return Heap::undefined_value(); | 1175 return Heap::undefined_value(); |
| 1145 } | 1176 } |
| 1146 | 1177 |
| 1147 // TODO(1236192): Most runtime routines don't need the number of | 1178 // TODO(1236192): Most runtime routines don't need the number of |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1379 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 1349 mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 1380 mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 1350 mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); | 1381 mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); |
| 1351 lea(edx, FieldOperand(edx, Code::kHeaderSize)); | 1382 lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| 1352 | 1383 |
| 1353 ParameterCount expected(ebx); | 1384 ParameterCount expected(ebx); |
| 1354 InvokeCode(Operand(edx), expected, actual, flag); | 1385 InvokeCode(Operand(edx), expected, actual, flag); |
| 1355 } | 1386 } |
| 1356 | 1387 |
| 1357 | 1388 |
| 1389 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 1390 const ParameterCount& actual, |
| 1391 InvokeFlag flag) { |
| 1392 ASSERT(function->is_compiled()); |
| 1393 // Get the function and setup the context. |
| 1394 mov(edi, Immediate(Handle<JSFunction>(function))); |
| 1395 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 1396 |
| 1397 // Invoke the cached code. |
| 1398 Handle<Code> code(function->code()); |
| 1399 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 1400 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); |
| 1401 } |
| 1402 |
| 1403 |
| 1358 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { | 1404 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) { |
| 1359 bool resolved; | |
| 1360 Handle<Code> code = ResolveBuiltin(id, &resolved); | |
| 1361 | |
| 1362 // Calls are not allowed in some stubs. | 1405 // Calls are not allowed in some stubs. |
| 1363 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); | 1406 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); |
| 1364 | 1407 |
| 1365 // Rely on the assertion to check that the number of provided | 1408 // Rely on the assertion to check that the number of provided |
| 1366 // arguments match the expected number of arguments. Fake a | 1409 // arguments match the expected number of arguments. Fake a |
| 1367 // parameter count to avoid emitting code to do the check. | 1410 // parameter count to avoid emitting code to do the check. |
| 1368 ParameterCount expected(0); | 1411 ParameterCount expected(0); |
| 1369 InvokeCode(Handle<Code>(code), expected, expected, | 1412 GetBuiltinEntry(edx, id); |
| 1370 RelocInfo::CODE_TARGET, flag); | 1413 InvokeCode(Operand(edx), expected, expected, flag); |
| 1371 | |
| 1372 const char* name = Builtins::GetName(id); | |
| 1373 int argc = Builtins::GetArgumentsCount(id); | |
| 1374 | |
| 1375 if (!resolved) { | |
| 1376 uint32_t flags = | |
| 1377 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | | |
| 1378 Bootstrapper::FixupFlagsUseCodeObject::encode(false); | |
| 1379 Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name }; | |
| 1380 unresolved_.Add(entry); | |
| 1381 } | |
| 1382 } | 1414 } |
| 1383 | 1415 |
| 1384 | 1416 |
| 1385 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 1417 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
| 1386 bool resolved; | 1418 // Load the JavaScript builtin function from the builtins object. |
| 1387 Handle<Code> code = ResolveBuiltin(id, &resolved); | 1419 mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 1388 | 1420 mov(edi, FieldOperand(edi, GlobalObject::kBuiltinsOffset)); |
| 1389 const char* name = Builtins::GetName(id); | 1421 int builtins_offset = |
| 1390 int argc = Builtins::GetArgumentsCount(id); | 1422 JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); |
| 1391 | 1423 mov(edi, FieldOperand(edi, builtins_offset)); |
| 1392 mov(Operand(target), Immediate(code)); | 1424 // Load the code entry point from the function into the target register. |
| 1393 if (!resolved) { | 1425 mov(target, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 1394 uint32_t flags = | 1426 mov(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset)); |
| 1395 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | | |
| 1396 Bootstrapper::FixupFlagsUseCodeObject::encode(true); | |
| 1397 Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name }; | |
| 1398 unresolved_.Add(entry); | |
| 1399 } | |
| 1400 add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1427 add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 1401 } | 1428 } |
| 1402 | 1429 |
| 1403 | 1430 |
| 1404 Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, | |
| 1405 bool* resolved) { | |
| 1406 // Move the builtin function into the temporary function slot by | |
| 1407 // reading it from the builtins object. NOTE: We should be able to | |
| 1408 // reduce this to two instructions by putting the function table in | |
| 1409 // the global object instead of the "builtins" object and by using a | |
| 1410 // real register for the function. | |
| 1411 mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
| 1412 mov(edx, FieldOperand(edx, GlobalObject::kBuiltinsOffset)); | |
| 1413 int builtins_offset = | |
| 1414 JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); | |
| 1415 mov(edi, FieldOperand(edx, builtins_offset)); | |
| 1416 | |
| 1417 return Builtins::GetCode(id, resolved); | |
| 1418 } | |
| 1419 | |
| 1420 | |
| 1421 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 1431 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
| 1422 if (context_chain_length > 0) { | 1432 if (context_chain_length > 0) { |
| 1423 // Move up the chain of contexts to the context containing the slot. | 1433 // Move up the chain of contexts to the context containing the slot. |
| 1424 mov(dst, Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); | 1434 mov(dst, Operand(esi, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 1425 // Load the function context (which is the incoming, outer context). | 1435 // Load the function context (which is the incoming, outer context). |
| 1426 mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); | 1436 mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); |
| 1427 for (int i = 1; i < context_chain_length; i++) { | 1437 for (int i = 1; i < context_chain_length; i++) { |
| 1428 mov(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); | 1438 mov(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX))); |
| 1429 mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); | 1439 mov(dst, FieldOperand(dst, JSFunction::kContextOffset)); |
| 1430 } | 1440 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 | 1562 |
| 1553 push(eax); | 1563 push(eax); |
| 1554 push(Immediate(p0)); | 1564 push(Immediate(p0)); |
| 1555 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); | 1565 push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0)))); |
| 1556 CallRuntime(Runtime::kAbort, 2); | 1566 CallRuntime(Runtime::kAbort, 2); |
| 1557 // will not return here | 1567 // will not return here |
| 1558 int3(); | 1568 int3(); |
| 1559 } | 1569 } |
| 1560 | 1570 |
| 1561 | 1571 |
| 1572 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii( |
| 1573 Register instance_type, |
| 1574 Register scratch, |
| 1575 Label *failure) { |
| 1576 if (!scratch.is(instance_type)) { |
| 1577 mov(scratch, instance_type); |
| 1578 } |
| 1579 and_(scratch, |
| 1580 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask); |
| 1581 cmp(scratch, kStringTag | kSeqStringTag | kAsciiStringTag); |
| 1582 j(not_equal, failure); |
| 1583 } |
| 1584 |
| 1585 |
| 1562 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, | 1586 void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1, |
| 1563 Register object2, | 1587 Register object2, |
| 1564 Register scratch1, | 1588 Register scratch1, |
| 1565 Register scratch2, | 1589 Register scratch2, |
| 1566 Label* failure) { | 1590 Label* failure) { |
| 1567 // Check that both objects are not smis. | 1591 // Check that both objects are not smis. |
| 1568 ASSERT_EQ(0, kSmiTag); | 1592 ASSERT_EQ(0, kSmiTag); |
| 1569 mov(scratch1, Operand(object1)); | 1593 mov(scratch1, Operand(object1)); |
| 1570 and_(scratch1, Operand(object2)); | 1594 and_(scratch1, Operand(object2)); |
| 1571 test(scratch1, Immediate(kSmiTagMask)); | 1595 test(scratch1, Immediate(kSmiTagMask)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1604 // Indicate that code has changed. | 1628 // Indicate that code has changed. |
| 1605 CPU::FlushICache(address_, size_); | 1629 CPU::FlushICache(address_, size_); |
| 1606 | 1630 |
| 1607 // Check that the code was patched as expected. | 1631 // Check that the code was patched as expected. |
| 1608 ASSERT(masm_.pc_ == address_ + size_); | 1632 ASSERT(masm_.pc_ == address_ + size_); |
| 1609 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1633 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 1610 } | 1634 } |
| 1611 | 1635 |
| 1612 | 1636 |
| 1613 } } // namespace v8::internal | 1637 } } // namespace v8::internal |
| OLD | NEW |