Index: src/x64/macro-assembler-x64.cc |
=================================================================== |
--- src/x64/macro-assembler-x64.cc (revision 10404) |
+++ src/x64/macro-assembler-x64.cc (working copy) |
@@ -1,4 +1,4 @@ |
-// Copyright 2011 the V8 project authors. All rights reserved. |
+// Copyright 2012 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -495,7 +495,7 @@ |
// from the real pointer as a smi. |
intptr_t p1 = reinterpret_cast<intptr_t>(msg); |
intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; |
- // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag. |
+ // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. |
ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); |
#ifdef DEBUG |
if (msg != NULL) { |
@@ -2739,15 +2739,48 @@ |
} |
+void MacroAssembler::CompareMap(Register obj, |
+ Handle<Map> map, |
+ Label* early_success, |
+ CompareMapMode mode) { |
+ Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
+ if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { |
+ Map* transitioned_fast_element_map( |
+ map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); |
+ ASSERT(transitioned_fast_element_map == NULL || |
+ map->elements_kind() != FAST_ELEMENTS); |
+ if (transitioned_fast_element_map != NULL) { |
+ j(equal, early_success, Label::kNear); |
+ Cmp(FieldOperand(obj, HeapObject::kMapOffset), |
+ Handle<Map>(transitioned_fast_element_map)); |
+ } |
+ |
+ Map* transitioned_double_map( |
+ map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); |
+ ASSERT(transitioned_double_map == NULL || |
+ map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); |
+ if (transitioned_double_map != NULL) { |
+ j(equal, early_success, Label::kNear); |
+ Cmp(FieldOperand(obj, HeapObject::kMapOffset), |
+ Handle<Map>(transitioned_double_map)); |
+ } |
+ } |
+} |
+ |
+ |
void MacroAssembler::CheckMap(Register obj, |
Handle<Map> map, |
Label* fail, |
- SmiCheckType smi_check_type) { |
+ SmiCheckType smi_check_type, |
+ CompareMapMode mode) { |
if (smi_check_type == DO_SMI_CHECK) { |
JumpIfSmi(obj, fail); |
} |
- Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
+ |
+ Label success; |
+ CompareMap(obj, map, &success, mode); |
j(not_equal, fail); |
+ bind(&success); |
} |
@@ -3198,7 +3231,7 @@ |
void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
- // Setup the frame structure on the stack. |
+ // Set up the frame structure on the stack. |
// All constants are relative to the frame pointer of the exit frame. |
ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |
@@ -3258,7 +3291,7 @@ |
void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { |
EnterExitFramePrologue(true); |
- // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, |
+ // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame, |
// so it must be retained across the C-call. |
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
lea(r15, Operand(rbp, r14, times_pointer_size, offset)); |
@@ -3386,6 +3419,42 @@ |
} |
+void MacroAssembler::GetNumberHash(Register r0, Register scratch) { |
+ // First of all we assign the hash seed to scratch. |
+ LoadRoot(scratch, Heap::kHashSeedRootIndex); |
+ SmiToInteger32(scratch, scratch); |
+ |
+ // Xor original key with a seed. |
+ xorl(r0, scratch); |
+ |
+ // Compute the hash code from the untagged key. This must be kept in sync |
+ // with ComputeIntegerHash in utils.h. |
+ // |
+ // hash = ~hash + (hash << 15); |
+ movl(scratch, r0); |
+ notl(r0); |
+ shll(scratch, Immediate(15)); |
+ addl(r0, scratch); |
+ // hash = hash ^ (hash >> 12); |
+ movl(scratch, r0); |
+ shrl(scratch, Immediate(12)); |
+ xorl(r0, scratch); |
+ // hash = hash + (hash << 2); |
+ leal(r0, Operand(r0, r0, times_4, 0)); |
+ // hash = hash ^ (hash >> 4); |
+ movl(scratch, r0); |
+ shrl(scratch, Immediate(4)); |
+ xorl(r0, scratch); |
+ // hash = hash * 2057; |
+ imull(r0, r0, Immediate(2057)); |
+ // hash = hash ^ (hash >> 16); |
+ movl(scratch, r0); |
+ shrl(scratch, Immediate(16)); |
+ xorl(r0, scratch); |
+} |
+ |
+ |
+ |
void MacroAssembler::LoadFromNumberDictionary(Label* miss, |
Register elements, |
Register key, |
@@ -3416,34 +3485,11 @@ |
Label done; |
- // Compute the hash code from the untagged key. This must be kept in sync |
- // with ComputeIntegerHash in utils.h. |
- // |
- // hash = ~hash + (hash << 15); |
- movl(r1, r0); |
- notl(r0); |
- shll(r1, Immediate(15)); |
- addl(r0, r1); |
- // hash = hash ^ (hash >> 12); |
- movl(r1, r0); |
- shrl(r1, Immediate(12)); |
- xorl(r0, r1); |
- // hash = hash + (hash << 2); |
- leal(r0, Operand(r0, r0, times_4, 0)); |
- // hash = hash ^ (hash >> 4); |
- movl(r1, r0); |
- shrl(r1, Immediate(4)); |
- xorl(r0, r1); |
- // hash = hash * 2057; |
- imull(r0, r0, Immediate(2057)); |
- // hash = hash ^ (hash >> 16); |
- movl(r1, r0); |
- shrl(r1, Immediate(16)); |
- xorl(r0, r1); |
+ GetNumberHash(r0, r1); |
// Compute capacity mask. |
- SmiToInteger32(r1, |
- FieldOperand(elements, NumberDictionary::kCapacityOffset)); |
+ SmiToInteger32(r1, FieldOperand(elements, |
+ SeededNumberDictionary::kCapacityOffset)); |
decl(r1); |
// Generate an unrolled loop that performs a few probes before giving up. |
@@ -3453,19 +3499,19 @@ |
movq(r2, r0); |
// Compute the masked index: (hash + i + i * i) & mask. |
if (i > 0) { |
- addl(r2, Immediate(NumberDictionary::GetProbeOffset(i))); |
+ addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); |
} |
and_(r2, r1); |
// Scale the index by multiplying by the entry size. |
- ASSERT(NumberDictionary::kEntrySize == 3); |
+ ASSERT(SeededNumberDictionary::kEntrySize == 3); |
lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
// Check if the key matches. |
cmpq(key, FieldOperand(elements, |
r2, |
times_pointer_size, |
- NumberDictionary::kElementsStartOffset)); |
+ SeededNumberDictionary::kElementsStartOffset)); |
if (i != (kProbes - 1)) { |
j(equal, &done); |
} else { |
@@ -3476,7 +3522,7 @@ |
bind(&done); |
// Check that the value is a normal propety. |
const int kDetailsOffset = |
- NumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
+ SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |
ASSERT_EQ(NORMAL, 0); |
Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |
Smi::FromInt(PropertyDetails::TypeField::kMask)); |
@@ -3484,7 +3530,7 @@ |
// Get the value at the masked, scaled index. |
const int kValueOffset = |
- NumberDictionary::kElementsStartOffset + kPointerSize; |
+ SeededNumberDictionary::kElementsStartOffset + kPointerSize; |
movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
} |