OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2317 __ j(equal, &done, Label::kNear); | 2317 __ j(equal, &done, Label::kNear); |
2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2319 Heap::kFixedCOWArrayMapRootIndex); | 2319 Heap::kFixedCOWArrayMapRootIndex); |
2320 __ j(equal, &done, Label::kNear); | 2320 __ j(equal, &done, Label::kNear); |
2321 Register temp((result.is(rax)) ? rbx : rax); | 2321 Register temp((result.is(rax)) ? rbx : rax); |
2322 __ push(temp); | 2322 __ push(temp); |
2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); | 2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); |
2325 __ and_(temp, Immediate(Map::kElementsKindMask)); | 2325 __ and_(temp, Immediate(Map::kElementsKindMask)); |
2326 __ shr(temp, Immediate(Map::kElementsKindShift)); | 2326 __ shr(temp, Immediate(Map::kElementsKindShift)); |
2327 __ cmpl(temp, Immediate(FAST_ELEMENTS)); | 2327 __ cmpl(temp, Immediate(GetInitialFastElementsKind())); |
2328 __ j(equal, &ok, Label::kNear); | 2328 __ j(less, &fail, Label::kNear); |
2329 __ cmpl(temp, Immediate(TERMINAL_FAST_ELEMENTS_KIND)); | |
2330 __ j(less_equal, &ok, Label::kNear); | |
2329 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2331 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2330 __ j(less, &fail, Label::kNear); | 2332 __ j(less, &fail, Label::kNear); |
2331 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2333 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2332 __ j(less_equal, &ok, Label::kNear); | 2334 __ j(less_equal, &ok, Label::kNear); |
2333 __ bind(&fail); | 2335 __ bind(&fail); |
2334 __ Abort("Check for fast or external elements failed"); | 2336 __ Abort("Check for fast or external elements failed"); |
2335 __ bind(&ok); | 2337 __ bind(&ok); |
2336 __ pop(temp); | 2338 __ pop(temp); |
2337 __ bind(&done); | 2339 __ bind(&done); |
2338 } | 2340 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2380 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2382 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
2381 DeoptimizeIf(equal, instr->environment()); | 2383 DeoptimizeIf(equal, instr->environment()); |
2382 } | 2384 } |
2383 } | 2385 } |
2384 | 2386 |
2385 | 2387 |
2386 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2388 void LCodeGen::DoLoadKeyedFastDoubleElement( |
2387 LLoadKeyedFastDoubleElement* instr) { | 2389 LLoadKeyedFastDoubleElement* instr) { |
2388 XMMRegister result(ToDoubleRegister(instr->result())); | 2390 XMMRegister result(ToDoubleRegister(instr->result())); |
2389 | 2391 |
2390 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2392 if (instr->hydrogen()->RequiresHoleCheck()) { |
2391 sizeof(kHoleNanLower32); | 2393 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
2392 Operand hole_check_operand = BuildFastArrayOperand( | 2394 sizeof(kHoleNanLower32); |
2393 instr->elements(), | 2395 Operand hole_check_operand = BuildFastArrayOperand( |
2394 instr->key(), | 2396 instr->elements(), |
2395 FAST_DOUBLE_ELEMENTS, | 2397 instr->key(), |
2396 offset); | 2398 FAST_DOUBLE_ELEMENTS, |
2397 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 2399 offset); |
2398 DeoptimizeIf(equal, instr->environment()); | 2400 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
2401 DeoptimizeIf(equal, instr->environment()); | |
2402 } | |
2399 | 2403 |
2400 Operand double_load_operand = BuildFastArrayOperand( | 2404 Operand double_load_operand = BuildFastArrayOperand( |
2401 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, | 2405 instr->elements(), instr->key(), FAST_DOUBLE_ELEMENTS, |
2402 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 2406 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
2403 __ movsd(result, double_load_operand); | 2407 __ movsd(result, double_load_operand); |
2404 } | 2408 } |
2405 | 2409 |
2406 | 2410 |
2407 Operand LCodeGen::BuildFastArrayOperand( | 2411 Operand LCodeGen::BuildFastArrayOperand( |
2408 LOperand* elements_pointer, | 2412 LOperand* elements_pointer, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2460 __ movl(result, operand); | 2464 __ movl(result, operand); |
2461 __ testl(result, result); | 2465 __ testl(result, result); |
2462 // TODO(danno): we could be more clever here, perhaps having a special | 2466 // TODO(danno): we could be more clever here, perhaps having a special |
2463 // version of the stub that detects if the overflow case actually | 2467 // version of the stub that detects if the overflow case actually |
2464 // happens, and generate code that returns a double rather than int. | 2468 // happens, and generate code that returns a double rather than int. |
2465 DeoptimizeIf(negative, instr->environment()); | 2469 DeoptimizeIf(negative, instr->environment()); |
2466 break; | 2470 break; |
2467 case EXTERNAL_FLOAT_ELEMENTS: | 2471 case EXTERNAL_FLOAT_ELEMENTS: |
2468 case EXTERNAL_DOUBLE_ELEMENTS: | 2472 case EXTERNAL_DOUBLE_ELEMENTS: |
2469 case FAST_ELEMENTS: | 2473 case FAST_ELEMENTS: |
2470 case FAST_SMI_ONLY_ELEMENTS: | 2474 case FAST_SMI_ELEMENTS: |
2471 case FAST_DOUBLE_ELEMENTS: | 2475 case FAST_DOUBLE_ELEMENTS: |
2476 case FAST_HOLEY_ELEMENTS: | |
2477 case FAST_HOLEY_SMI_ELEMENTS: | |
2478 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
2472 case DICTIONARY_ELEMENTS: | 2479 case DICTIONARY_ELEMENTS: |
2473 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2480 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2474 UNREACHABLE(); | 2481 UNREACHABLE(); |
2475 break; | 2482 break; |
2476 } | 2483 } |
2477 } | 2484 } |
2478 } | 2485 } |
2479 | 2486 |
2480 | 2487 |
2481 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2488 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3351 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3358 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3352 __ movw(operand, value); | 3359 __ movw(operand, value); |
3353 break; | 3360 break; |
3354 case EXTERNAL_INT_ELEMENTS: | 3361 case EXTERNAL_INT_ELEMENTS: |
3355 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3362 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3356 __ movl(operand, value); | 3363 __ movl(operand, value); |
3357 break; | 3364 break; |
3358 case EXTERNAL_FLOAT_ELEMENTS: | 3365 case EXTERNAL_FLOAT_ELEMENTS: |
3359 case EXTERNAL_DOUBLE_ELEMENTS: | 3366 case EXTERNAL_DOUBLE_ELEMENTS: |
3360 case FAST_ELEMENTS: | 3367 case FAST_ELEMENTS: |
3361 case FAST_SMI_ONLY_ELEMENTS: | 3368 case FAST_SMI_ELEMENTS: |
3362 case FAST_DOUBLE_ELEMENTS: | 3369 case FAST_DOUBLE_ELEMENTS: |
3370 case FAST_HOLEY_ELEMENTS: | |
3371 case FAST_HOLEY_SMI_ELEMENTS: | |
3372 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3363 case DICTIONARY_ELEMENTS: | 3373 case DICTIONARY_ELEMENTS: |
3364 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3374 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3365 UNREACHABLE(); | 3375 UNREACHABLE(); |
3366 break; | 3376 break; |
3367 } | 3377 } |
3368 } | 3378 } |
3369 } | 3379 } |
3370 | 3380 |
3371 | 3381 |
3372 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3382 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3477 | 3487 |
3478 Handle<Map> from_map = instr->original_map(); | 3488 Handle<Map> from_map = instr->original_map(); |
3479 Handle<Map> to_map = instr->transitioned_map(); | 3489 Handle<Map> to_map = instr->transitioned_map(); |
3480 ElementsKind from_kind = from_map->elements_kind(); | 3490 ElementsKind from_kind = from_map->elements_kind(); |
3481 ElementsKind to_kind = to_map->elements_kind(); | 3491 ElementsKind to_kind = to_map->elements_kind(); |
3482 | 3492 |
3483 Label not_applicable; | 3493 Label not_applicable; |
3484 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3494 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3485 __ j(not_equal, ¬_applicable); | 3495 __ j(not_equal, ¬_applicable); |
3486 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3496 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
3487 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3497 bool simple_map_change = (GetHoleyElementsKind(from_kind) == to_kind) || |
3498 (IsFastSmiElementsKind(from_kind) && | |
3499 IsFastObjectElementsKind(to_kind)); | |
3500 if (simple_map_change) { | |
3488 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3501 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3489 // Write barrier. | 3502 // Write barrier. |
3490 ASSERT_NE(instr->temp_reg(), NULL); | 3503 ASSERT_NE(instr->temp_reg(), NULL); |
3491 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3504 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3492 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3505 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
3493 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 3506 } else if (IsFastSmiElementsKind(from_kind) && |
3494 to_kind == FAST_DOUBLE_ELEMENTS) { | 3507 IsFastDoubleElementsKind(to_kind)) { |
3495 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3508 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3496 ASSERT(fixed_object_reg.is(rdx)); | 3509 ASSERT(fixed_object_reg.is(rdx)); |
3497 ASSERT(new_map_reg.is(rbx)); | 3510 ASSERT(new_map_reg.is(rbx)); |
3498 __ movq(fixed_object_reg, object_reg); | 3511 __ movq(fixed_object_reg, object_reg); |
3499 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3512 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3500 RelocInfo::CODE_TARGET, instr); | 3513 RelocInfo::CODE_TARGET, instr); |
3501 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3514 } else if (IsFastDoubleElementsKind(from_kind) && |
3515 IsFastElementsKind(to_kind)) { | |
Jakob Kummerow
2012/05/22 17:36:49
IsFastObjectElementsKind(to_kind) ?
danno
2012/05/23 14:25:36
Done.
| |
3502 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3516 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3503 ASSERT(fixed_object_reg.is(rdx)); | 3517 ASSERT(fixed_object_reg.is(rdx)); |
3504 ASSERT(new_map_reg.is(rbx)); | 3518 ASSERT(new_map_reg.is(rbx)); |
3505 __ movq(fixed_object_reg, object_reg); | 3519 __ movq(fixed_object_reg, object_reg); |
3506 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3520 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3507 RelocInfo::CODE_TARGET, instr); | 3521 RelocInfo::CODE_TARGET, instr); |
3508 } else { | 3522 } else { |
3509 UNREACHABLE(); | 3523 UNREACHABLE(); |
3510 } | 3524 } |
3511 __ bind(¬_applicable); | 3525 __ bind(¬_applicable); |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4165 } | 4179 } |
4166 | 4180 |
4167 | 4181 |
4168 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4182 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
4169 Heap* heap = isolate()->heap(); | 4183 Heap* heap = isolate()->heap(); |
4170 ElementsKind boilerplate_elements_kind = | 4184 ElementsKind boilerplate_elements_kind = |
4171 instr->hydrogen()->boilerplate_elements_kind(); | 4185 instr->hydrogen()->boilerplate_elements_kind(); |
4172 | 4186 |
4173 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4187 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4174 // than the expected one. The check isn't necessary if the boilerplate has | 4188 // than the expected one. The check isn't necessary if the boilerplate has |
4175 // already been converted to FAST_ELEMENTS. | 4189 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
4176 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4190 if (CanTransitionToMoreGeneralFastElementsKind( |
4191 boilerplate_elements_kind, true)) { | |
4177 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 4192 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |
4178 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 4193 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
4179 // Load the map's "bit field 2". | 4194 // Load the map's "bit field 2". |
4180 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 4195 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |
4181 // Retrieve elements_kind from bit field 2. | 4196 // Retrieve elements_kind from bit field 2. |
4182 __ and_(rbx, Immediate(Map::kElementsKindMask)); | 4197 __ and_(rbx, Immediate(Map::kElementsKindMask)); |
4183 __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 4198 __ cmpb(rbx, Immediate(boilerplate_elements_kind << |
4184 Map::kElementsKindShift)); | 4199 Map::kElementsKindShift)); |
4185 DeoptimizeIf(not_equal, instr->environment()); | 4200 DeoptimizeIf(not_equal, instr->environment()); |
4186 } | 4201 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4312 } | 4327 } |
4313 } | 4328 } |
4314 } | 4329 } |
4315 | 4330 |
4316 | 4331 |
4317 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { | 4332 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { |
4318 int size = instr->hydrogen()->total_size(); | 4333 int size = instr->hydrogen()->total_size(); |
4319 ElementsKind boilerplate_elements_kind = | 4334 ElementsKind boilerplate_elements_kind = |
4320 instr->hydrogen()->boilerplate()->GetElementsKind(); | 4335 instr->hydrogen()->boilerplate()->GetElementsKind(); |
4321 | 4336 |
4322 // Deopt if the literal boilerplate ElementsKind is of a type different than | 4337 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4323 // the expected one. The check isn't necessary if the boilerplate has already | 4338 // than the expected one. The check isn't necessary if the boilerplate has |
4324 // been converted to FAST_ELEMENTS. | 4339 // already been converted to FAST_ELEMENTS. |
Jakob Kummerow
2012/05/22 17:36:49
nit: s/FAST_ELEMENTS/TERMINAL_FAST_ELEMENTS_KIND/
danno
2012/05/23 14:25:36
Done.
| |
4325 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4340 if (CanTransitionToMoreGeneralFastElementsKind( |
4341 boilerplate_elements_kind, true)) { | |
4326 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 4342 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |
4327 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); | 4343 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); |
4328 // Load the map's "bit field 2". | 4344 // Load the map's "bit field 2". |
4329 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); | 4345 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); |
4330 // Retrieve elements_kind from bit field 2. | 4346 // Retrieve elements_kind from bit field 2. |
4331 __ and_(rcx, Immediate(Map::kElementsKindMask)); | 4347 __ and_(rcx, Immediate(Map::kElementsKindMask)); |
4332 __ cmpb(rcx, Immediate(boilerplate_elements_kind << | 4348 __ cmpb(rcx, Immediate(boilerplate_elements_kind << |
4333 Map::kElementsKindShift)); | 4349 Map::kElementsKindShift)); |
4334 DeoptimizeIf(not_equal, instr->environment()); | 4350 DeoptimizeIf(not_equal, instr->environment()); |
4335 } | 4351 } |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4811 FixedArray::kHeaderSize - kPointerSize)); | 4827 FixedArray::kHeaderSize - kPointerSize)); |
4812 __ bind(&done); | 4828 __ bind(&done); |
4813 } | 4829 } |
4814 | 4830 |
4815 | 4831 |
4816 #undef __ | 4832 #undef __ |
4817 | 4833 |
4818 } } // namespace v8::internal | 4834 } } // namespace v8::internal |
4819 | 4835 |
4820 #endif // V8_TARGET_ARCH_X64 | 4836 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |