| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2396 LLoadKeyedFastDoubleElement* instr) { | 2398 LLoadKeyedFastDoubleElement* instr) { |
| 2397 XMMRegister result(ToDoubleRegister(instr->result())); | 2399 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2398 | 2400 |
| 2399 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { | 2401 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { |
| 2400 // Sign extend key because it could be a 32 bit negative value | 2402 // Sign extend key because it could be a 32 bit negative value |
| 2401 // and the dehoisted address computation happens in 64 bits | 2403 // and the dehoisted address computation happens in 64 bits |
| 2402 Register key_reg = ToRegister(instr->key()); | 2404 Register key_reg = ToRegister(instr->key()); |
| 2403 __ movsxlq(key_reg, key_reg); | 2405 __ movsxlq(key_reg, key_reg); |
| 2404 } | 2406 } |
| 2405 | 2407 |
| 2406 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2408 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2407 sizeof(kHoleNanLower32); | 2409 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
| 2408 Operand hole_check_operand = BuildFastArrayOperand( | 2410 sizeof(kHoleNanLower32); |
| 2409 instr->elements(), | 2411 Operand hole_check_operand = BuildFastArrayOperand( |
| 2410 instr->key(), | 2412 instr->elements(), |
| 2411 FAST_DOUBLE_ELEMENTS, | 2413 instr->key(), |
| 2412 offset, | 2414 FAST_DOUBLE_ELEMENTS, |
| 2413 instr->additional_index()); | 2415 offset, |
| 2414 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 2416 instr->additional_index()); |
| 2415 DeoptimizeIf(equal, instr->environment()); | 2417 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2418 DeoptimizeIf(equal, instr->environment()); |
| 2419 } |
| 2416 | 2420 |
| 2417 Operand double_load_operand = BuildFastArrayOperand( | 2421 Operand double_load_operand = BuildFastArrayOperand( |
| 2418 instr->elements(), | 2422 instr->elements(), |
| 2419 instr->key(), | 2423 instr->key(), |
| 2420 FAST_DOUBLE_ELEMENTS, | 2424 FAST_DOUBLE_ELEMENTS, |
| 2421 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 2425 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 2422 instr->additional_index()); | 2426 instr->additional_index()); |
| 2423 __ movsd(result, double_load_operand); | 2427 __ movsd(result, double_load_operand); |
| 2424 } | 2428 } |
| 2425 | 2429 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 __ movl(result, operand); | 2498 __ movl(result, operand); |
| 2495 __ testl(result, result); | 2499 __ testl(result, result); |
| 2496 // TODO(danno): we could be more clever here, perhaps having a special | 2500 // TODO(danno): we could be more clever here, perhaps having a special |
| 2497 // version of the stub that detects if the overflow case actually | 2501 // version of the stub that detects if the overflow case actually |
| 2498 // happens, and generate code that returns a double rather than int. | 2502 // happens, and generate code that returns a double rather than int. |
| 2499 DeoptimizeIf(negative, instr->environment()); | 2503 DeoptimizeIf(negative, instr->environment()); |
| 2500 break; | 2504 break; |
| 2501 case EXTERNAL_FLOAT_ELEMENTS: | 2505 case EXTERNAL_FLOAT_ELEMENTS: |
| 2502 case EXTERNAL_DOUBLE_ELEMENTS: | 2506 case EXTERNAL_DOUBLE_ELEMENTS: |
| 2503 case FAST_ELEMENTS: | 2507 case FAST_ELEMENTS: |
| 2504 case FAST_SMI_ONLY_ELEMENTS: | 2508 case FAST_SMI_ELEMENTS: |
| 2505 case FAST_DOUBLE_ELEMENTS: | 2509 case FAST_DOUBLE_ELEMENTS: |
| 2510 case FAST_HOLEY_ELEMENTS: |
| 2511 case FAST_HOLEY_SMI_ELEMENTS: |
| 2512 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 2506 case DICTIONARY_ELEMENTS: | 2513 case DICTIONARY_ELEMENTS: |
| 2507 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2514 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 2508 UNREACHABLE(); | 2515 UNREACHABLE(); |
| 2509 break; | 2516 break; |
| 2510 } | 2517 } |
| 2511 } | 2518 } |
| 2512 } | 2519 } |
| 2513 | 2520 |
| 2514 | 2521 |
| 2515 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2522 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| (...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3396 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3403 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3397 __ movw(operand, value); | 3404 __ movw(operand, value); |
| 3398 break; | 3405 break; |
| 3399 case EXTERNAL_INT_ELEMENTS: | 3406 case EXTERNAL_INT_ELEMENTS: |
| 3400 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3407 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3401 __ movl(operand, value); | 3408 __ movl(operand, value); |
| 3402 break; | 3409 break; |
| 3403 case EXTERNAL_FLOAT_ELEMENTS: | 3410 case EXTERNAL_FLOAT_ELEMENTS: |
| 3404 case EXTERNAL_DOUBLE_ELEMENTS: | 3411 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3405 case FAST_ELEMENTS: | 3412 case FAST_ELEMENTS: |
| 3406 case FAST_SMI_ONLY_ELEMENTS: | 3413 case FAST_SMI_ELEMENTS: |
| 3407 case FAST_DOUBLE_ELEMENTS: | 3414 case FAST_DOUBLE_ELEMENTS: |
| 3415 case FAST_HOLEY_ELEMENTS: |
| 3416 case FAST_HOLEY_SMI_ELEMENTS: |
| 3417 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3408 case DICTIONARY_ELEMENTS: | 3418 case DICTIONARY_ELEMENTS: |
| 3409 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3419 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3410 UNREACHABLE(); | 3420 UNREACHABLE(); |
| 3411 break; | 3421 break; |
| 3412 } | 3422 } |
| 3413 } | 3423 } |
| 3414 } | 3424 } |
| 3415 | 3425 |
| 3416 | 3426 |
| 3417 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3427 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3532 | 3542 |
| 3533 Handle<Map> from_map = instr->original_map(); | 3543 Handle<Map> from_map = instr->original_map(); |
| 3534 Handle<Map> to_map = instr->transitioned_map(); | 3544 Handle<Map> to_map = instr->transitioned_map(); |
| 3535 ElementsKind from_kind = from_map->elements_kind(); | 3545 ElementsKind from_kind = from_map->elements_kind(); |
| 3536 ElementsKind to_kind = to_map->elements_kind(); | 3546 ElementsKind to_kind = to_map->elements_kind(); |
| 3537 | 3547 |
| 3538 Label not_applicable; | 3548 Label not_applicable; |
| 3539 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3549 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
| 3540 __ j(not_equal, ¬_applicable); | 3550 __ j(not_equal, ¬_applicable); |
| 3541 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3551 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
| 3542 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3552 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 3543 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3553 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
| 3544 // Write barrier. | 3554 // Write barrier. |
| 3545 ASSERT_NE(instr->temp_reg(), NULL); | 3555 ASSERT_NE(instr->temp_reg(), NULL); |
| 3546 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3556 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 3547 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3557 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
| 3548 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 3558 } else if (IsFastSmiElementsKind(from_kind) && |
| 3549 to_kind == FAST_DOUBLE_ELEMENTS) { | 3559 IsFastDoubleElementsKind(to_kind)) { |
| 3550 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3560 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 3551 ASSERT(fixed_object_reg.is(rdx)); | 3561 ASSERT(fixed_object_reg.is(rdx)); |
| 3552 ASSERT(new_map_reg.is(rbx)); | 3562 ASSERT(new_map_reg.is(rbx)); |
| 3553 __ movq(fixed_object_reg, object_reg); | 3563 __ movq(fixed_object_reg, object_reg); |
| 3554 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3564 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
| 3555 RelocInfo::CODE_TARGET, instr); | 3565 RelocInfo::CODE_TARGET, instr); |
| 3556 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3566 } else if (IsFastDoubleElementsKind(from_kind) && |
| 3567 IsFastObjectElementsKind(to_kind)) { |
| 3557 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3568 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
| 3558 ASSERT(fixed_object_reg.is(rdx)); | 3569 ASSERT(fixed_object_reg.is(rdx)); |
| 3559 ASSERT(new_map_reg.is(rbx)); | 3570 ASSERT(new_map_reg.is(rbx)); |
| 3560 __ movq(fixed_object_reg, object_reg); | 3571 __ movq(fixed_object_reg, object_reg); |
| 3561 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3572 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
| 3562 RelocInfo::CODE_TARGET, instr); | 3573 RelocInfo::CODE_TARGET, instr); |
| 3563 } else { | 3574 } else { |
| 3564 UNREACHABLE(); | 3575 UNREACHABLE(); |
| 3565 } | 3576 } |
| 3566 __ bind(¬_applicable); | 3577 __ bind(¬_applicable); |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4220 } | 4231 } |
| 4221 | 4232 |
| 4222 | 4233 |
| 4223 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4234 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| 4224 Heap* heap = isolate()->heap(); | 4235 Heap* heap = isolate()->heap(); |
| 4225 ElementsKind boilerplate_elements_kind = | 4236 ElementsKind boilerplate_elements_kind = |
| 4226 instr->hydrogen()->boilerplate_elements_kind(); | 4237 instr->hydrogen()->boilerplate_elements_kind(); |
| 4227 | 4238 |
| 4228 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4239 // Deopt if the array literal boilerplate ElementsKind is of a type different |
| 4229 // than the expected one. The check isn't necessary if the boilerplate has | 4240 // than the expected one. The check isn't necessary if the boilerplate has |
| 4230 // already been converted to FAST_ELEMENTS. | 4241 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
| 4231 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4242 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4243 boilerplate_elements_kind, true)) { |
| 4232 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 4244 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |
| 4233 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 4245 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 4234 // Load the map's "bit field 2". | 4246 // Load the map's "bit field 2". |
| 4235 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 4247 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |
| 4236 // Retrieve elements_kind from bit field 2. | 4248 // Retrieve elements_kind from bit field 2. |
| 4237 __ and_(rbx, Immediate(Map::kElementsKindMask)); | 4249 __ and_(rbx, Immediate(Map::kElementsKindMask)); |
| 4238 __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 4250 __ cmpb(rbx, Immediate(boilerplate_elements_kind << |
| 4239 Map::kElementsKindShift)); | 4251 Map::kElementsKindShift)); |
| 4240 DeoptimizeIf(not_equal, instr->environment()); | 4252 DeoptimizeIf(not_equal, instr->environment()); |
| 4241 } | 4253 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4367 } | 4379 } |
| 4368 } | 4380 } |
| 4369 } | 4381 } |
| 4370 | 4382 |
| 4371 | 4383 |
| 4372 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { | 4384 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { |
| 4373 int size = instr->hydrogen()->total_size(); | 4385 int size = instr->hydrogen()->total_size(); |
| 4374 ElementsKind boilerplate_elements_kind = | 4386 ElementsKind boilerplate_elements_kind = |
| 4375 instr->hydrogen()->boilerplate()->GetElementsKind(); | 4387 instr->hydrogen()->boilerplate()->GetElementsKind(); |
| 4376 | 4388 |
| 4377 // Deopt if the literal boilerplate ElementsKind is of a type different than | 4389 // Deopt if the array literal boilerplate ElementsKind is of a type different |
| 4378 // the expected one. The check isn't necessary if the boilerplate has already | 4390 // than the expected one. The check isn't necessary if the boilerplate has |
| 4379 // been converted to FAST_ELEMENTS. | 4391 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
| 4380 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4392 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4393 boilerplate_elements_kind, true)) { |
| 4381 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 4394 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |
| 4382 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); | 4395 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 4383 // Load the map's "bit field 2". | 4396 // Load the map's "bit field 2". |
| 4384 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); | 4397 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); |
| 4385 // Retrieve elements_kind from bit field 2. | 4398 // Retrieve elements_kind from bit field 2. |
| 4386 __ and_(rcx, Immediate(Map::kElementsKindMask)); | 4399 __ and_(rcx, Immediate(Map::kElementsKindMask)); |
| 4387 __ cmpb(rcx, Immediate(boilerplate_elements_kind << | 4400 __ cmpb(rcx, Immediate(boilerplate_elements_kind << |
| 4388 Map::kElementsKindShift)); | 4401 Map::kElementsKindShift)); |
| 4389 DeoptimizeIf(not_equal, instr->environment()); | 4402 DeoptimizeIf(not_equal, instr->environment()); |
| 4390 } | 4403 } |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4866 FixedArray::kHeaderSize - kPointerSize)); | 4879 FixedArray::kHeaderSize - kPointerSize)); |
| 4867 __ bind(&done); | 4880 __ bind(&done); |
| 4868 } | 4881 } |
| 4869 | 4882 |
| 4870 | 4883 |
| 4871 #undef __ | 4884 #undef __ |
| 4872 | 4885 |
| 4873 } } // namespace v8::internal | 4886 } } // namespace v8::internal |
| 4874 | 4887 |
| 4875 #endif // V8_TARGET_ARCH_X64 | 4888 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |