OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 Label not_identical; | 253 Label not_identical; |
254 Label heap_number, return_equal; | 254 Label heap_number, return_equal; |
255 __ cmp(r3, r4); | 255 __ cmp(r3, r4); |
256 __ bne(¬_identical); | 256 __ bne(¬_identical); |
257 | 257 |
258 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 258 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
259 // so we do the second best thing - test it ourselves. | 259 // so we do the second best thing - test it ourselves. |
260 // They are both equal and they are not both Smis so both of them are not | 260 // They are both equal and they are not both Smis so both of them are not |
261 // Smis. If it's not a heap number, then return equal. | 261 // Smis. If it's not a heap number, then return equal. |
262 if (cond == lt || cond == gt) { | 262 if (cond == lt || cond == gt) { |
| 263 Label not_simd; |
263 // Call runtime on identical JSObjects. | 264 // Call runtime on identical JSObjects. |
264 __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE); | 265 __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE); |
265 __ bge(slow); | 266 __ bge(slow); |
266 // Call runtime on identical symbols since we need to throw a TypeError. | 267 // Call runtime on identical symbols since we need to throw a TypeError. |
267 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 268 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
268 __ beq(slow); | 269 __ beq(slow); |
269 // Call runtime on identical SIMD values since we must throw a TypeError. | 270 // Call runtime on identical SIMD values since we must throw a TypeError. |
270 __ cmpi(r7, Operand(FLOAT32X4_TYPE)); | 271 __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE)); |
271 __ beq(slow); | 272 __ blt(¬_simd); |
| 273 __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE)); |
| 274 __ ble(slow); |
| 275 __ bind(¬_simd); |
272 if (is_strong(strength)) { | 276 if (is_strong(strength)) { |
273 // Call the runtime on anything that is converted in the semantics, since | 277 // Call the runtime on anything that is converted in the semantics, since |
274 // we need to throw a TypeError. Smis have already been ruled out. | 278 // we need to throw a TypeError. Smis have already been ruled out. |
275 __ cmpi(r7, Operand(HEAP_NUMBER_TYPE)); | 279 __ cmpi(r7, Operand(HEAP_NUMBER_TYPE)); |
276 __ beq(&return_equal); | 280 __ beq(&return_equal); |
277 __ andi(r0, r7, Operand(kIsNotStringMask)); | 281 __ andi(r0, r7, Operand(kIsNotStringMask)); |
278 __ bne(slow, cr0); | 282 __ bne(slow, cr0); |
279 } | 283 } |
280 } else { | 284 } else { |
281 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); | 285 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); |
282 __ beq(&heap_number); | 286 __ beq(&heap_number); |
283 // Comparing JS objects with <=, >= is complicated. | 287 // Comparing JS objects with <=, >= is complicated. |
284 if (cond != eq) { | 288 if (cond != eq) { |
| 289 Label not_simd; |
285 __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE)); | 290 __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE)); |
286 __ bge(slow); | 291 __ bge(slow); |
287 // Call runtime on identical symbols since we need to throw a TypeError. | 292 // Call runtime on identical symbols since we need to throw a TypeError. |
288 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 293 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
289 __ beq(slow); | 294 __ beq(slow); |
290 // Call runtime on identical SIMD values since we must throw a TypeError. | 295 // Call runtime on identical SIMD values since we must throw a TypeError. |
291 __ cmpi(r7, Operand(FLOAT32X4_TYPE)); | 296 __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE)); |
292 __ beq(slow); | 297 __ blt(¬_simd); |
| 298 __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE)); |
| 299 __ ble(slow); |
| 300 __ bind(¬_simd); |
293 if (is_strong(strength)) { | 301 if (is_strong(strength)) { |
294 // Call the runtime on anything that is converted in the semantics, | 302 // Call the runtime on anything that is converted in the semantics, |
295 // since we need to throw a TypeError. Smis and heap numbers have | 303 // since we need to throw a TypeError. Smis and heap numbers have |
296 // already been ruled out. | 304 // already been ruled out. |
297 __ andi(r0, r7, Operand(kIsNotStringMask)); | 305 __ andi(r0, r7, Operand(kIsNotStringMask)); |
298 __ bne(slow, cr0); | 306 __ bne(slow, cr0); |
299 } | 307 } |
300 // Normally here we fall through to return_equal, but undefined is | 308 // Normally here we fall through to return_equal, but undefined is |
301 // special: (undefined == undefined) == true, but | 309 // special: (undefined == undefined) == true, but |
302 // (undefined <= undefined) == false! See ECMAScript 11.8.5. | 310 // (undefined <= undefined) == false! See ECMAScript 11.8.5. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 __ cmpi(r3, Operand::Zero()); | 362 __ cmpi(r3, Operand::Zero()); |
355 // For equal we already have the right value in r3: Return zero (equal) | 363 // For equal we already have the right value in r3: Return zero (equal) |
356 // if all bits in mantissa are zero (it's an Infinity) and non-zero if | 364 // if all bits in mantissa are zero (it's an Infinity) and non-zero if |
357 // not (it's a NaN). For <= and >= we need to load r0 with the failing | 365 // not (it's a NaN). For <= and >= we need to load r0 with the failing |
358 // value if it's a NaN. | 366 // value if it's a NaN. |
359 if (cond != eq) { | 367 if (cond != eq) { |
360 if (CpuFeatures::IsSupported(ISELECT)) { | 368 if (CpuFeatures::IsSupported(ISELECT)) { |
361 __ li(r4, Operand((cond == le) ? GREATER : LESS)); | 369 __ li(r4, Operand((cond == le) ? GREATER : LESS)); |
362 __ isel(eq, r3, r3, r4); | 370 __ isel(eq, r3, r3, r4); |
363 } else { | 371 } else { |
| 372 Label not_equal; |
| 373 __ bne(¬_equal); |
364 // All-zero means Infinity means equal. | 374 // All-zero means Infinity means equal. |
365 __ Ret(eq); | 375 __ Ret(); |
| 376 __ bind(¬_equal); |
366 if (cond == le) { | 377 if (cond == le) { |
367 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. | 378 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. |
368 } else { | 379 } else { |
369 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. | 380 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. |
370 } | 381 } |
371 } | 382 } |
372 } | 383 } |
373 __ Ret(); | 384 __ Ret(); |
374 } | 385 } |
375 // No fall through here. | 386 // No fall through here. |
(...skipping 10 matching lines...) Expand all Loading... |
386 | 397 |
387 Label rhs_is_smi; | 398 Label rhs_is_smi; |
388 __ JumpIfSmi(rhs, &rhs_is_smi); | 399 __ JumpIfSmi(rhs, &rhs_is_smi); |
389 | 400 |
390 // Lhs is a Smi. Check whether the rhs is a heap number. | 401 // Lhs is a Smi. Check whether the rhs is a heap number. |
391 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); | 402 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); |
392 if (strict) { | 403 if (strict) { |
393 // If rhs is not a number and lhs is a Smi then strict equality cannot | 404 // If rhs is not a number and lhs is a Smi then strict equality cannot |
394 // succeed. Return non-equal | 405 // succeed. Return non-equal |
395 // If rhs is r3 then there is already a non zero value in it. | 406 // If rhs is r3 then there is already a non zero value in it. |
| 407 Label skip; |
| 408 __ beq(&skip); |
396 if (!rhs.is(r3)) { | 409 if (!rhs.is(r3)) { |
397 Label skip; | |
398 __ beq(&skip); | |
399 __ mov(r3, Operand(NOT_EQUAL)); | 410 __ mov(r3, Operand(NOT_EQUAL)); |
400 __ Ret(); | |
401 __ bind(&skip); | |
402 } else { | |
403 __ Ret(ne); | |
404 } | 411 } |
| 412 __ Ret(); |
| 413 __ bind(&skip); |
405 } else { | 414 } else { |
406 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 415 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
407 // the runtime. | 416 // the runtime. |
408 __ bne(slow); | 417 __ bne(slow); |
409 } | 418 } |
410 | 419 |
411 // Lhs is a smi, rhs is a number. | 420 // Lhs is a smi, rhs is a number. |
412 // Convert lhs to a double in d7. | 421 // Convert lhs to a double in d7. |
413 __ SmiToDouble(d7, lhs); | 422 __ SmiToDouble(d7, lhs); |
414 // Load the double from rhs, tagged HeapNumber r3, to d6. | 423 // Load the double from rhs, tagged HeapNumber r3, to d6. |
415 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 424 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
416 | 425 |
417 // We now have both loaded as doubles but we can skip the lhs nan check | 426 // We now have both loaded as doubles but we can skip the lhs nan check |
418 // since it's a smi. | 427 // since it's a smi. |
419 __ b(lhs_not_nan); | 428 __ b(lhs_not_nan); |
420 | 429 |
421 __ bind(&rhs_is_smi); | 430 __ bind(&rhs_is_smi); |
422 // Rhs is a smi. Check whether the non-smi lhs is a heap number. | 431 // Rhs is a smi. Check whether the non-smi lhs is a heap number. |
423 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); | 432 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); |
424 if (strict) { | 433 if (strict) { |
425 // If lhs is not a number and rhs is a smi then strict equality cannot | 434 // If lhs is not a number and rhs is a smi then strict equality cannot |
426 // succeed. Return non-equal. | 435 // succeed. Return non-equal. |
427 // If lhs is r3 then there is already a non zero value in it. | 436 // If lhs is r3 then there is already a non zero value in it. |
| 437 Label skip; |
| 438 __ beq(&skip); |
428 if (!lhs.is(r3)) { | 439 if (!lhs.is(r3)) { |
429 Label skip; | |
430 __ beq(&skip); | |
431 __ mov(r3, Operand(NOT_EQUAL)); | 440 __ mov(r3, Operand(NOT_EQUAL)); |
432 __ Ret(); | |
433 __ bind(&skip); | |
434 } else { | |
435 __ Ret(ne); | |
436 } | 441 } |
| 442 __ Ret(); |
| 443 __ bind(&skip); |
437 } else { | 444 } else { |
438 // Smi compared non-strictly with a non-smi non-heap-number. Call | 445 // Smi compared non-strictly with a non-smi non-heap-number. Call |
439 // the runtime. | 446 // the runtime. |
440 __ bne(slow); | 447 __ bne(slow); |
441 } | 448 } |
442 | 449 |
443 // Rhs is a smi, lhs is a heap number. | 450 // Rhs is a smi, lhs is a heap number. |
444 // Load the double from lhs, tagged HeapNumber r4, to d7. | 451 // Load the double from lhs, tagged HeapNumber r4, to d7. |
445 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 452 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
446 // Convert rhs to a double in d6. | 453 // Convert rhs to a double in d6. |
(...skipping 3513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3960 // Handle not identical strings. | 3967 // Handle not identical strings. |
3961 | 3968 |
3962 // Check that both strings are internalized strings. If they are, we're done | 3969 // Check that both strings are internalized strings. If they are, we're done |
3963 // because we already know they are not identical. We know they are both | 3970 // because we already know they are not identical. We know they are both |
3964 // strings. | 3971 // strings. |
3965 if (equality) { | 3972 if (equality) { |
3966 DCHECK(GetCondition() == eq); | 3973 DCHECK(GetCondition() == eq); |
3967 STATIC_ASSERT(kInternalizedTag == 0); | 3974 STATIC_ASSERT(kInternalizedTag == 0); |
3968 __ orx(tmp3, tmp1, tmp2); | 3975 __ orx(tmp3, tmp1, tmp2); |
3969 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); | 3976 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); |
| 3977 __ bne(&is_symbol, cr0); |
3970 // Make sure r3 is non-zero. At this point input operands are | 3978 // Make sure r3 is non-zero. At this point input operands are |
3971 // guaranteed to be non-zero. | 3979 // guaranteed to be non-zero. |
3972 DCHECK(right.is(r3)); | 3980 DCHECK(right.is(r3)); |
3973 __ Ret(eq, cr0); | 3981 __ Ret(); |
| 3982 __ bind(&is_symbol); |
3974 } | 3983 } |
3975 | 3984 |
3976 // Check that both strings are sequential one-byte. | 3985 // Check that both strings are sequential one-byte. |
3977 Label runtime; | 3986 Label runtime; |
3978 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, | 3987 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, |
3979 &runtime); | 3988 &runtime); |
3980 | 3989 |
3981 // Compare flat one-byte strings. Returns when done. | 3990 // Compare flat one-byte strings. Returns when done. |
3982 if (equality) { | 3991 if (equality) { |
3983 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, | 3992 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4200 // the hash in a separate instruction. The value hash + i + i * i is right | 4209 // the hash in a separate instruction. The value hash + i + i * i is right |
4201 // shifted in the following and instruction. | 4210 // shifted in the following and instruction. |
4202 DCHECK(NameDictionary::GetProbeOffset(i) < | 4211 DCHECK(NameDictionary::GetProbeOffset(i) < |
4203 1 << (32 - Name::kHashFieldOffset)); | 4212 1 << (32 - Name::kHashFieldOffset)); |
4204 __ addi(scratch2, scratch2, | 4213 __ addi(scratch2, scratch2, |
4205 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); | 4214 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); |
4206 } | 4215 } |
4207 __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); | 4216 __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); |
4208 __ and_(scratch2, scratch1, scratch2); | 4217 __ and_(scratch2, scratch1, scratch2); |
4209 | 4218 |
4210 // Scale the index by multiplying by the entry size. | 4219 // Scale the index by multiplying by the element size. |
4211 STATIC_ASSERT(NameDictionary::kEntrySize == 3); | 4220 STATIC_ASSERT(NameDictionary::kEntrySize == 3); |
4212 // scratch2 = scratch2 * 3. | 4221 // scratch2 = scratch2 * 3. |
4213 __ ShiftLeftImm(ip, scratch2, Operand(1)); | 4222 __ ShiftLeftImm(ip, scratch2, Operand(1)); |
4214 __ add(scratch2, scratch2, ip); | 4223 __ add(scratch2, scratch2, ip); |
4215 | 4224 |
4216 // Check if the key is identical to the name. | 4225 // Check if the key is identical to the name. |
4217 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); | 4226 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); |
4218 __ add(scratch2, elements, ip); | 4227 __ add(scratch2, elements, ip); |
4219 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); | 4228 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); |
4220 __ cmp(name, ip); | 4229 __ cmp(name, ip); |
(...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5305 Label fast_elements_case; | 5314 Label fast_elements_case; |
5306 __ cmpi(r6, Operand(FAST_ELEMENTS)); | 5315 __ cmpi(r6, Operand(FAST_ELEMENTS)); |
5307 __ beq(&fast_elements_case); | 5316 __ beq(&fast_elements_case); |
5308 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 5317 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
5309 | 5318 |
5310 __ bind(&fast_elements_case); | 5319 __ bind(&fast_elements_case); |
5311 GenerateCase(masm, FAST_ELEMENTS); | 5320 GenerateCase(masm, FAST_ELEMENTS); |
5312 } | 5321 } |
5313 | 5322 |
5314 | 5323 |
5315 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
5316 Register context = cp; | |
5317 Register result = r3; | |
5318 Register slot = r5; | |
5319 | |
5320 // Go up the context chain to the script context. | |
5321 for (int i = 0; i < depth(); ++i) { | |
5322 __ LoadP(result, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
5323 context = result; | |
5324 } | |
5325 | |
5326 // Load the PropertyCell value at the specified slot. | |
5327 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); | |
5328 __ add(result, context, r0); | |
5329 __ LoadP(result, ContextOperand(result)); | |
5330 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | |
5331 | |
5332 // If the result is not the_hole, return. Otherwise, handle in the runtime. | |
5333 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | |
5334 __ Ret(ne); | |
5335 | |
5336 // Fallback to runtime. | |
5337 __ SmiTag(slot); | |
5338 __ Push(slot); | |
5339 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); | |
5340 } | |
5341 | |
5342 | |
5343 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
5344 Register value = r3; | |
5345 Register slot = r5; | |
5346 | |
5347 Register cell = r4; | |
5348 Register cell_details = r6; | |
5349 Register cell_value = r7; | |
5350 Register cell_value_map = r8; | |
5351 Register scratch = r9; | |
5352 | |
5353 Register context = cp; | |
5354 Register context_temp = cell; | |
5355 | |
5356 Label fast_heapobject_case, fast_smi_case, slow_case; | |
5357 | |
5358 if (FLAG_debug_code) { | |
5359 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); | |
5360 __ Check(ne, kUnexpectedValue); | |
5361 } | |
5362 | |
5363 // Go up the context chain to the script context. | |
5364 for (int i = 0; i < depth(); i++) { | |
5365 __ LoadP(context_temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
5366 context = context_temp; | |
5367 } | |
5368 | |
5369 // Load the PropertyCell at the specified slot. | |
5370 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); | |
5371 __ add(cell, context, r0); | |
5372 __ LoadP(cell, ContextOperand(cell)); | |
5373 | |
5374 // Load PropertyDetails for the cell (actually only the cell_type and kind). | |
5375 __ LoadP(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); | |
5376 __ SmiUntag(cell_details); | |
5377 __ andi(cell_details, cell_details, | |
5378 Operand(PropertyDetails::PropertyCellTypeField::kMask | | |
5379 PropertyDetails::KindField::kMask | | |
5380 PropertyDetails::kAttributesReadOnlyMask)); | |
5381 | |
5382 // Check if PropertyCell holds mutable data. | |
5383 Label not_mutable_data; | |
5384 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( | |
5385 PropertyCellType::kMutable) | | |
5386 PropertyDetails::KindField::encode(kData))); | |
5387 __ bne(¬_mutable_data); | |
5388 __ JumpIfSmi(value, &fast_smi_case); | |
5389 | |
5390 __ bind(&fast_heapobject_case); | |
5391 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); | |
5392 // RecordWriteField clobbers the value register, so we copy it before the | |
5393 // call. | |
5394 __ mr(r6, value); | |
5395 __ RecordWriteField(cell, PropertyCell::kValueOffset, r6, scratch, | |
5396 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
5397 OMIT_SMI_CHECK); | |
5398 __ Ret(); | |
5399 | |
5400 __ bind(¬_mutable_data); | |
5401 // Check if PropertyCell value matches the new value (relevant for Constant, | |
5402 // ConstantType and Undefined cells). | |
5403 Label not_same_value; | |
5404 __ LoadP(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset)); | |
5405 __ cmp(cell_value, value); | |
5406 __ bne(¬_same_value); | |
5407 | |
5408 // Make sure the PropertyCell is not marked READ_ONLY. | |
5409 __ andi(r0, cell_details, Operand(PropertyDetails::kAttributesReadOnlyMask)); | |
5410 __ bne(&slow_case, cr0); | |
5411 | |
5412 if (FLAG_debug_code) { | |
5413 Label done; | |
5414 // This can only be true for Constant, ConstantType and Undefined cells, | |
5415 // because we never store the_hole via this stub. | |
5416 __ cmpi(cell_details, | |
5417 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
5418 PropertyCellType::kConstant) | | |
5419 PropertyDetails::KindField::encode(kData))); | |
5420 __ beq(&done); | |
5421 __ cmpi(cell_details, | |
5422 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
5423 PropertyCellType::kConstantType) | | |
5424 PropertyDetails::KindField::encode(kData))); | |
5425 __ beq(&done); | |
5426 __ cmpi(cell_details, | |
5427 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
5428 PropertyCellType::kUndefined) | | |
5429 PropertyDetails::KindField::encode(kData))); | |
5430 __ Check(eq, kUnexpectedValue); | |
5431 __ bind(&done); | |
5432 } | |
5433 __ Ret(); | |
5434 __ bind(¬_same_value); | |
5435 | |
5436 // Check if PropertyCell contains data with constant type (and is not | |
5437 // READ_ONLY). | |
5438 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( | |
5439 PropertyCellType::kConstantType) | | |
5440 PropertyDetails::KindField::encode(kData))); | |
5441 __ bne(&slow_case); | |
5442 | |
5443 // Now either both old and new values must be smis or both must be heap | |
5444 // objects with same map. | |
5445 Label value_is_heap_object; | |
5446 __ JumpIfNotSmi(value, &value_is_heap_object); | |
5447 __ JumpIfNotSmi(cell_value, &slow_case); | |
5448 // Old and new values are smis, no need for a write barrier here. | |
5449 __ bind(&fast_smi_case); | |
5450 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); | |
5451 __ Ret(); | |
5452 | |
5453 __ bind(&value_is_heap_object); | |
5454 __ JumpIfSmi(cell_value, &slow_case); | |
5455 | |
5456 __ LoadP(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset)); | |
5457 __ LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | |
5458 __ cmp(cell_value_map, scratch); | |
5459 __ beq(&fast_heapobject_case); | |
5460 | |
5461 // Fallback to runtime. | |
5462 __ bind(&slow_case); | |
5463 __ SmiTag(slot); | |
5464 __ Push(slot, value); | |
5465 __ TailCallRuntime(is_strict(language_mode()) | |
5466 ? Runtime::kStoreGlobalViaContext_Strict | |
5467 : Runtime::kStoreGlobalViaContext_Sloppy, | |
5468 2, 1); | |
5469 } | |
5470 | |
5471 | |
5472 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 5324 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
5473 return ref0.address() - ref1.address(); | 5325 return ref0.address() - ref1.address(); |
5474 } | 5326 } |
5475 | 5327 |
5476 | 5328 |
5477 // Calls an API function. Allocates HandleScope, extracts returned value | 5329 // Calls an API function. Allocates HandleScope, extracts returned value |
5478 // from handle and propagates exceptions. Restores context. stack_space | 5330 // from handle and propagates exceptions. Restores context. stack_space |
5479 // - space to be unwound on exit (includes the call JS arguments space and | 5331 // - space to be unwound on exit (includes the call JS arguments space and |
5480 // the additional space allocated for the fast call). | 5332 // the additional space allocated for the fast call). |
5481 static void CallApiFunctionAndReturn(MacroAssembler* masm, | 5333 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5826 kStackUnwindSpace, NULL, | 5678 kStackUnwindSpace, NULL, |
5827 MemOperand(fp, 6 * kPointerSize), NULL); | 5679 MemOperand(fp, 6 * kPointerSize), NULL); |
5828 } | 5680 } |
5829 | 5681 |
5830 | 5682 |
5831 #undef __ | 5683 #undef __ |
5832 } // namespace internal | 5684 } // namespace internal |
5833 } // namespace v8 | 5685 } // namespace v8 |
5834 | 5686 |
5835 #endif // V8_TARGET_ARCH_PPC | 5687 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |