| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 Register reg = object_reg; | 462 Register reg = object_reg; |
| 463 int depth = 1; | 463 int depth = 1; |
| 464 | 464 |
| 465 // Check the maps in the prototype chain. | 465 // Check the maps in the prototype chain. |
| 466 // Traverse the prototype chain from the object and do map checks. | 466 // Traverse the prototype chain from the object and do map checks. |
| 467 while (object != holder) { | 467 while (object != holder) { |
| 468 depth++; | 468 depth++; |
| 469 | 469 |
| 470 // Only global objects and objects that do not require access | 470 // Only global objects and objects that do not require access |
| 471 // checks are allowed in stubs. | 471 // checks are allowed in stubs. |
| 472 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); | 472 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 473 | 473 |
| 474 JSObject* prototype = JSObject::cast(object->GetPrototype()); | 474 JSObject* prototype = JSObject::cast(object->GetPrototype()); |
| 475 if (Heap::InNewSpace(prototype)) { | 475 if (Heap::InNewSpace(prototype)) { |
| 476 // Get the map of the current object. | 476 // Get the map of the current object. |
| 477 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 477 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 478 cmp(Operand(scratch), Immediate(Handle<Map>(object->map()))); | 478 cmp(Operand(scratch), Immediate(Handle<Map>(object->map()))); |
| 479 // Branch on the result of the map check. | 479 // Branch on the result of the map check. |
| 480 j(not_equal, miss, not_taken); | 480 j(not_equal, miss, not_taken); |
| 481 // Check access rights to the global object. This has to happen | 481 // Check access rights to the global object. This has to happen |
| 482 // after the map check so that we know that the object is | 482 // after the map check so that we know that the object is |
| 483 // actually a global object. | 483 // actually a global object. |
| 484 if (object->IsJSGlobalObject()) { | 484 if (object->IsJSGlobalProxy()) { |
| 485 CheckAccessGlobal(reg, scratch, miss); | 485 CheckAccessGlobalProxy(reg, scratch, miss); |
| 486 // Restore scratch register to be the map of the object. We | 486 |
| 487 // load the prototype from the map in the scratch register. | 487 // Restore scratch register to be the map of the object. |
| 488 // We load the prototype from the map in the scratch register. |
| 488 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 489 mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 489 } | 490 } |
| 490 // The prototype is in new space; we cannot store a reference | 491 // The prototype is in new space; we cannot store a reference |
| 491 // to it in the code. Load it from the map. | 492 // to it in the code. Load it from the map. |
| 492 reg = holder_reg; // from now the object is in holder_reg | 493 reg = holder_reg; // from now the object is in holder_reg |
| 493 mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); | 494 mov(reg, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 495 |
| 494 } else { | 496 } else { |
| 495 // Check the map of the current object. | 497 // Check the map of the current object. |
| 496 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 498 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 497 Immediate(Handle<Map>(object->map()))); | 499 Immediate(Handle<Map>(object->map()))); |
| 498 // Branch on the result of the map check. | 500 // Branch on the result of the map check. |
| 499 j(not_equal, miss, not_taken); | 501 j(not_equal, miss, not_taken); |
| 500 // Check access rights to the global object. This has to happen | 502 // Check access rights to the global object. This has to happen |
| 501 // after the map check so that we know that the object is | 503 // after the map check so that we know that the object is |
| 502 // actually a global object. | 504 // actually a global object. |
| 503 if (object->IsJSGlobalObject()) { | 505 if (object->IsJSGlobalProxy()) { |
| 504 CheckAccessGlobal(reg, scratch, miss); | 506 CheckAccessGlobalProxy(reg, scratch, miss); |
| 505 } | 507 } |
| 506 // The prototype is in old space; load it directly. | 508 // The prototype is in old space; load it directly. |
| 507 reg = holder_reg; // from now the object is in holder_reg | 509 reg = holder_reg; // from now the object is in holder_reg |
| 508 mov(reg, Handle<JSObject>(prototype)); | 510 mov(reg, Handle<JSObject>(prototype)); |
| 509 } | 511 } |
| 510 | 512 |
| 511 // Go to the next object in the prototype chain. | 513 // Go to the next object in the prototype chain. |
| 512 object = prototype; | 514 object = prototype; |
| 513 } | 515 } |
| 514 | 516 |
| 515 // Check the holder map. | 517 // Check the holder map. |
| 516 cmp(FieldOperand(reg, HeapObject::kMapOffset), | 518 cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 517 Immediate(Handle<Map>(holder->map()))); | 519 Immediate(Handle<Map>(holder->map()))); |
| 518 j(not_equal, miss, not_taken); | 520 j(not_equal, miss, not_taken); |
| 519 | 521 |
| 520 // Log the check depth. | 522 // Log the check depth. |
| 521 LOG(IntEvent("check-maps-depth", depth)); | 523 LOG(IntEvent("check-maps-depth", depth)); |
| 522 | 524 |
| 523 // Perform security check for access to the global object and return | 525 // Perform security check for access to the global object and return |
| 524 // the holder register. | 526 // the holder register. |
| 525 ASSERT(object == holder); | 527 ASSERT(object == holder); |
| 526 ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded()); | 528 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 527 if (object->IsJSGlobalObject()) { | 529 if (object->IsJSGlobalProxy()) { |
| 528 CheckAccessGlobal(reg, scratch, miss); | 530 CheckAccessGlobalProxy(reg, scratch, miss); |
| 529 } | 531 } |
| 530 return reg; | 532 return reg; |
| 531 } | 533 } |
| 532 | 534 |
| 533 | 535 |
| 534 void MacroAssembler::CheckAccessGlobal(Register holder_reg, | 536 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 535 Register scratch, | 537 Register scratch, |
| 536 Label* miss) { | 538 Label* miss) { |
| 539 Label same_contexts; |
| 540 |
| 537 ASSERT(!holder_reg.is(scratch)); | 541 ASSERT(!holder_reg.is(scratch)); |
| 538 | 542 |
| 539 // Load the security context. | 543 // Load current lexical context from the stack frame. |
| 540 ExternalReference security_context = | 544 mov(scratch, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 541 ExternalReference(Top::k_security_context_address); | 545 |
| 542 mov(scratch, Operand::StaticVariable(security_context)); | 546 // When generating debug code, make sure the lexical context is set. |
| 543 // When generating debug code, make sure the security context is set. | |
| 544 if (FLAG_debug_code) { | 547 if (FLAG_debug_code) { |
| 545 cmp(Operand(scratch), Immediate(0)); | 548 cmp(Operand(scratch), Immediate(0)); |
| 546 Check(not_equal, "we should not have an empty security context"); | 549 Check(not_equal, "we should not have an empty lexical context"); |
| 547 } | 550 } |
| 548 // Load the global object of the security context. | 551 // Load the global context of the current context. |
| 549 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 552 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 550 mov(scratch, FieldOperand(scratch, offset)); | 553 mov(scratch, FieldOperand(scratch, offset)); |
| 554 mov(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 555 |
| 556 // Check the context is a global context. |
| 557 if (FLAG_debug_code) { |
| 558 push(scratch); |
| 559 // Read the first word and compare to global_context_map. |
| 560 mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 561 cmp(scratch, Factory::global_context_map()); |
| 562 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 563 pop(scratch); |
| 564 } |
| 565 |
| 566 // Check if both contexts are the same. |
| 567 cmp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 568 j(equal, &same_contexts, taken); |
| 569 |
| 570 // Compare security tokens, save holder_reg on the stack so we can use it |
| 571 // as a temporary register. |
| 572 // |
| 573 // TODO(119): avoid push(holder_reg)/pop(holder_reg) |
| 574 push(holder_reg); |
| 551 // Check that the security token in the calling global object is | 575 // Check that the security token in the calling global object is |
| 552 // compatible with the security token in the receiving global | 576 // compatible with the security token in the receiving global |
| 553 // object. | 577 // object. |
| 554 mov(scratch, FieldOperand(scratch, JSGlobalObject::kSecurityTokenOffset)); | 578 mov(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 555 cmp(scratch, FieldOperand(holder_reg, JSGlobalObject::kSecurityTokenOffset)); | 579 |
| 580 // Check the context is a global context. |
| 581 if (FLAG_debug_code) { |
| 582 cmp(holder_reg, Factory::null_value()); |
| 583 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 584 |
| 585 push(holder_reg); |
| 586 // Read the first word and compare to global_context_map(), |
| 587 mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 588 cmp(holder_reg, Factory::global_context_map()); |
| 589 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 590 pop(holder_reg); |
| 591 } |
| 592 |
| 593 int token_offset = Context::kHeaderSize + |
| 594 Context::SECURITY_TOKEN_INDEX * kPointerSize; |
| 595 mov(scratch, FieldOperand(scratch, token_offset)); |
| 596 cmp(scratch, FieldOperand(holder_reg, token_offset)); |
| 597 pop(holder_reg); |
| 556 j(not_equal, miss, not_taken); | 598 j(not_equal, miss, not_taken); |
| 599 |
| 600 bind(&same_contexts); |
| 557 } | 601 } |
| 558 | 602 |
| 559 | 603 |
| 560 void MacroAssembler::NegativeZeroTest(Register result, | 604 void MacroAssembler::NegativeZeroTest(Register result, |
| 561 Register op, | 605 Register op, |
| 562 Label* then_label) { | 606 Label* then_label) { |
| 563 Label ok; | 607 Label ok; |
| 564 test(result, Operand(result)); | 608 test(result, Operand(result)); |
| 565 j(not_zero, &ok, taken); | 609 j(not_zero, &ok, taken); |
| 566 test(op, Operand(op)); | 610 test(op, Operand(op)); |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 // Indicate that code has changed. | 1005 // Indicate that code has changed. |
| 962 CPU::FlushICache(address_, size_); | 1006 CPU::FlushICache(address_, size_); |
| 963 | 1007 |
| 964 // Check that the code was patched as expected. | 1008 // Check that the code was patched as expected. |
| 965 ASSERT(masm_.pc_ == address_ + size_); | 1009 ASSERT(masm_.pc_ == address_ + size_); |
| 966 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1010 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 967 } | 1011 } |
| 968 | 1012 |
| 969 | 1013 |
| 970 } } // namespace v8::internal | 1014 } } // namespace v8::internal |
| OLD | NEW |