Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: src/a64/lithium-codegen-a64.cc

Issue 131363008: A64: Synchronize with r15922. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | src/a64/macro-assembler-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 927 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 } 938 }
939 939
940 940
941 void LCodeGen::Deoptimize(LEnvironment* environment) { 941 void LCodeGen::Deoptimize(LEnvironment* environment) {
942 Deoptimizer::BailoutType bailout_type = info()->IsStub() ? Deoptimizer::LAZY 942 Deoptimizer::BailoutType bailout_type = info()->IsStub() ? Deoptimizer::LAZY
943 : Deoptimizer::EAGER; 943 : Deoptimizer::EAGER;
944 Deoptimize(environment, bailout_type); 944 Deoptimize(environment, bailout_type);
945 } 945 }
946 946
947 947
948 void LCodeGen::SoftDeoptimize(LEnvironment* environment) {
949 ASSERT(!info()->IsStub());
950 Deoptimize(environment, Deoptimizer::SOFT);
951 }
952
953
954 void LCodeGen::DeoptimizeIf(Condition cond, LEnvironment* environment) { 948 void LCodeGen::DeoptimizeIf(Condition cond, LEnvironment* environment) {
955 Label dont_deopt; 949 Label dont_deopt;
956 __ B(InvertCondition(cond), &dont_deopt); 950 __ B(InvertCondition(cond), &dont_deopt);
957 Deoptimize(environment); 951 Deoptimize(environment);
958 __ Bind(&dont_deopt); 952 __ Bind(&dont_deopt);
959 } 953 }
960 954
961 955
962 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) { 956 void LCodeGen::DeoptimizeIfZero(Register rt, LEnvironment* environment) {
963 Label dont_deopt; 957 Label dont_deopt;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 return DoubleRegister::FromAllocationIndex(op->index()); 1057 return DoubleRegister::FromAllocationIndex(op->index());
1064 } 1058 }
1065 1059
1066 1060
1067 Operand LCodeGen::ToOperand(LOperand* op) { 1061 Operand LCodeGen::ToOperand(LOperand* op) {
1068 ASSERT(op != NULL); 1062 ASSERT(op != NULL);
1069 if (op->IsConstantOperand()) { 1063 if (op->IsConstantOperand()) {
1070 LConstantOperand* const_op = LConstantOperand::cast(op); 1064 LConstantOperand* const_op = LConstantOperand::cast(op);
1071 HConstant* constant = chunk()->LookupConstant(const_op); 1065 HConstant* constant = chunk()->LookupConstant(const_op);
1072 Representation r = chunk_->LookupLiteralRepresentation(const_op); 1066 Representation r = chunk_->LookupLiteralRepresentation(const_op);
1073 if (r.IsInteger32()) { 1067 if (r.IsSmi()) {
1068 ASSERT(constant->HasSmiValue());
1069 return Operand(Smi::FromInt(constant->Integer32Value()));
1070 } else if (r.IsInteger32()) {
1074 ASSERT(constant->HasInteger32Value()); 1071 ASSERT(constant->HasInteger32Value());
1075 return Operand(constant->Integer32Value()); 1072 return Operand(constant->Integer32Value());
1076 } else if (r.IsDouble()) { 1073 } else if (r.IsDouble()) {
1077 Abort("ToOperand unsupported double immediate."); 1074 Abort("ToOperand unsupported double immediate.");
1078 } 1075 }
1079 ASSERT(r.IsTagged()); 1076 ASSERT(r.IsTagged());
1080 return Operand(constant->handle()); 1077 return Operand(constant->handle());
1081 } else if (op->IsRegister()) { 1078 } else if (op->IsRegister()) {
1082 return Operand(ToRegister(op)); 1079 return Operand(ToRegister(op));
1083 } else if (op->IsDoubleRegister()) { 1080 } else if (op->IsDoubleRegister()) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 Operand right = ToOperand32(instr->right()); 1290 Operand right = ToOperand32(instr->right());
1294 if (can_overflow) { 1291 if (can_overflow) {
1295 __ Adds(result, left, right); 1292 __ Adds(result, left, right);
1296 DeoptimizeIf(vs, instr->environment()); 1293 DeoptimizeIf(vs, instr->environment());
1297 } else { 1294 } else {
1298 __ Add(result, left, right); 1295 __ Add(result, left, right);
1299 } 1296 }
1300 } 1297 }
1301 1298
1302 1299
1300 void LCodeGen::DoAddS(LAddS* instr) {
1301 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1302 Register result = ToRegister(instr->result());
1303 Register left = ToRegister(instr->left());
1304 Operand right = ToOperand(instr->right());
1305 if (can_overflow) {
1306 __ Adds(result, left, right);
1307 DeoptimizeIf(vs, instr->environment());
1308 } else {
1309 __ Add(result, left, right);
1310 }
1311 }
1312
1313
1303 void LCodeGen::DoAllocate(LAllocate* instr) { 1314 void LCodeGen::DoAllocate(LAllocate* instr) {
1304 class DeferredAllocate: public LDeferredCode { 1315 class DeferredAllocate: public LDeferredCode {
1305 public: 1316 public:
1306 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 1317 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
1307 : LDeferredCode(codegen), instr_(instr) { } 1318 : LDeferredCode(codegen), instr_(instr) { }
1308 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 1319 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
1309 virtual LInstruction* instr() { return instr_; } 1320 virtual LInstruction* instr() { return instr_; }
1310 private: 1321 private:
1311 LAllocate* instr_; 1322 LAllocate* instr_;
1312 }; 1323 };
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1532 ASSERT(ToRegister(instr->left()).is(x1)); 1543 ASSERT(ToRegister(instr->left()).is(x1));
1533 ASSERT(ToRegister(instr->right()).is(x0)); 1544 ASSERT(ToRegister(instr->right()).is(x0));
1534 ASSERT(ToRegister(instr->result()).is(x0)); 1545 ASSERT(ToRegister(instr->result()).is(x0));
1535 1546
1536 BinaryOpStub stub(instr->op(), NO_OVERWRITE); 1547 BinaryOpStub stub(instr->op(), NO_OVERWRITE);
1537 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 1548 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
1538 } 1549 }
1539 1550
1540 1551
1541 void LCodeGen::DoBitI(LBitI* instr) { 1552 void LCodeGen::DoBitI(LBitI* instr) {
1542 LOperand* left_op = instr->left(); 1553 Register result = ToRegister32(instr->result());
1543 LOperand* right_op = instr->right(); 1554 Register left = ToRegister32(instr->left());
1544 Register left = ToRegister(left_op); 1555 Operand right = ToOperand32(instr->right());
1545 Register result = ToRegister(instr->result());
1546
1547 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
1548 Operand right = ToOperand(right_op);
1549 1556
1550 switch (instr->op()) { 1557 switch (instr->op()) {
1551 case Token::BIT_AND: __ And(result, left, right); break; 1558 case Token::BIT_AND: __ And(result, left, right); break;
1559 case Token::BIT_OR: __ Orr(result, left, right); break;
1560 case Token::BIT_XOR: __ Eor(result, left, right); break;
1561 default:
1562 UNREACHABLE();
1563 break;
1564 }
1565 }
1566
1567
1568 void LCodeGen::DoBitS(LBitS* instr) {
1569 Register result = ToRegister(instr->result());
1570 Register left = ToRegister(instr->left());
1571 Operand right = ToOperand(instr->right());
1572
1573 switch (instr->op()) {
1574 case Token::BIT_AND: __ And(result, left, right); break;
1552 case Token::BIT_OR: __ Orr(result, left, right); break; 1575 case Token::BIT_OR: __ Orr(result, left, right); break;
1553 case Token::BIT_XOR: __ Eor(result, left, right); break; 1576 case Token::BIT_XOR: __ Eor(result, left, right); break;
1554 default: 1577 default:
1555 UNREACHABLE(); 1578 UNREACHABLE();
1556 break; 1579 break;
1557 } 1580 }
1558 } 1581 }
1559 1582
1560 1583
1561 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1584 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1562 Register input = ToRegister(instr->value()).W(); 1585 Register input = ToRegister(instr->value()).W();
1563 Register result = ToRegister(instr->result()).W(); 1586 Register result = ToRegister(instr->result()).W();
1564 __ Mvn(result, input); 1587 __ Mvn(result, input);
1565 } 1588 }
1566 1589
1567 1590
1591 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
1592 if (FLAG_debug_code && check->hydrogen()->skip_check()) {
1593 __ Assert(InvertCondition(cc), "eliminated bounds check failed");
1594 } else {
1595 DeoptimizeIf(cc, check->environment());
1596 }
1597 }
1598
1599
1568 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) { 1600 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) {
1569 if (instr->hydrogen()->skip_check()) return; 1601 if (instr->hydrogen()->skip_check()) return;
1570 1602
1571 Register length = ToRegister(instr->length()); 1603 Register length = ToRegister(instr->length());
1572 1604
1573 if (instr->index()->IsConstantOperand()) { 1605 if (instr->index()->IsConstantOperand()) {
1574 int constant_index = 1606 int constant_index =
1575 ToInteger32(LConstantOperand::cast(instr->index())); 1607 ToInteger32(LConstantOperand::cast(instr->index()));
1576 1608
1577 if (instr->hydrogen()->length()->representation().IsSmi()) { 1609 if (instr->hydrogen()->length()->representation().IsSmi()) {
1578 __ Cmp(length, Operand(Smi::FromInt(constant_index))); 1610 __ Cmp(length, Operand(Smi::FromInt(constant_index)));
1579 } else { 1611 } else {
1580 __ Cmp(length, Operand(constant_index)); 1612 __ Cmp(length, Operand(constant_index));
1581 } 1613 }
1582 } else { 1614 } else {
1583 __ Cmp(length, ToRegister(instr->index())); 1615 __ Cmp(length, ToRegister(instr->index()));
1584 } 1616 }
1585 DeoptimizeIf(ls, instr->environment()); 1617 Condition condition = instr->hydrogen()->allow_equality() ? lo : ls;
1618 ApplyCheckIf(condition, instr);
1586 } 1619 }
1587 1620
1588 1621
1589 void LCodeGen::DoBranch(LBranch* instr) { 1622 void LCodeGen::DoBranch(LBranch* instr) {
1590 Representation r = instr->hydrogen()->value()->representation(); 1623 Representation r = instr->hydrogen()->value()->representation();
1591 Label* true_label = instr->TrueLabel(chunk_); 1624 Label* true_label = instr->TrueLabel(chunk_);
1592 Label* false_label = instr->FalseLabel(chunk_); 1625 Label* false_label = instr->FalseLabel(chunk_);
1593 1626
1594 if (r.IsInteger32()) { 1627 if (r.IsInteger32()) {
1595 ASSERT(!info()->IsStub()); 1628 ASSERT(!info()->IsStub());
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 } 1927 }
1895 1928
1896 1929
1897 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1930 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1898 // Record the address of the first unknown OSR value as the place to enter. 1931 // Record the address of the first unknown OSR value as the place to enter.
1899 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset(); 1932 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset();
1900 } 1933 }
1901 1934
1902 1935
1903 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 1936 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
1937 if (instr->hydrogen()->CanOmitMapChecks()) {
1938 ASSERT(instr->temp() == NULL);
1939 return;
1940 }
1941
1904 Register object = ToRegister(instr->value()); 1942 Register object = ToRegister(instr->value());
1905 Register map_reg = ToRegister(instr->temp()); 1943 Register map_reg = ToRegister(instr->temp());
1906 1944
1907 Label success; 1945 Label success;
1908 SmallMapList* map_set = instr->hydrogen()->map_set(); 1946 SmallMapList* map_set = instr->hydrogen()->map_set();
1909 __ Ldr(map_reg, FieldMemOperand(object, HeapObject::kMapOffset)); 1947 __ Ldr(map_reg, FieldMemOperand(object, HeapObject::kMapOffset));
1910 for (int i = 0; i < map_set->length(); i++) { 1948 for (int i = 0; i < map_set->length(); i++) {
1911 Handle<Map> map = map_set->at(i); 1949 Handle<Map> map = map_set->at(i);
1912 __ CompareMap(map_reg, map, &success); 1950 __ CompareMap(map_reg, map, &success);
1913 __ B(eq, &success); 1951 __ B(eq, &success);
(...skipping 10 matching lines...) Expand all
1924 if (!instr->hydrogen()->value()->IsHeapObject()) { 1962 if (!instr->hydrogen()->value()->IsHeapObject()) {
1925 // TODO(all): Depending of how we chose to implement the deopt, if we could 1963 // TODO(all): Depending of how we chose to implement the deopt, if we could
1926 // guarantee that we have a deopt handler reachable by a tbz instruction, 1964 // guarantee that we have a deopt handler reachable by a tbz instruction,
1927 // we could use tbz here and produce less code to support this instruction. 1965 // we could use tbz here and produce less code to support this instruction.
1928 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); 1966 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment());
1929 } 1967 }
1930 } 1968 }
1931 1969
1932 1970
1933 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 1971 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
1972 if (instr->hydrogen()->CanOmitPrototypeChecks()) {
1973 ASSERT(instr->temp1() == NULL);
1974 ASSERT(instr->temp2() == NULL);
1975 return;
1976 }
1977
1934 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); 1978 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes();
1935 ZoneList<Handle<Map> >* maps = instr->maps(); 1979 ZoneList<Handle<Map> >* maps = instr->maps();
1936 ASSERT(prototypes->length() == maps->length()); 1980 ASSERT(prototypes->length() == maps->length());
1937 1981
1938 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 1982 Label success, deopt;
1939 // TODO(jbramley): The temp registers are only needed in this case. 1983 Register temp1 = ToRegister(instr->temp1());
1940 Label success, deopt; 1984 Register temp2 = ToRegister(instr->temp2());
1941 Register temp1 = ToRegister(instr->temp1()); 1985 for (int i = 0; i < prototypes->length(); i++) {
1942 Register temp2 = ToRegister(instr->temp2()); 1986 __ LoadHeapObject(temp1, prototypes->at(i));
1943 for (int i = 0; i < prototypes->length(); i++) { 1987 __ Ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
1944 __ LoadHeapObject(temp1, prototypes->at(i)); 1988 __ CompareMap(temp2, maps->at(i), &success);
1945 __ Ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 1989 __ B(eq, &success);
1946 __ CompareMap(temp2, maps->at(i), &success);
1947 __ B(eq, &success);
1948 }
1949 // If we didn't match a map, deoptimize.
1950 Deoptimize(instr->environment());
1951 __ Bind(&success);
1952 } 1990 }
1991 // If we didn't match a map, deoptimize.
1992 Deoptimize(instr->environment());
1993 __ Bind(&success);
1953 } 1994 }
1954 1995
1955 1996
1956 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 1997 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
1957 Register value = ToRegister(instr->value()); 1998 Register value = ToRegister(instr->value());
1958 ASSERT(ToRegister(instr->result()).Is(value)); 1999 ASSERT(ToRegister(instr->result()).Is(value));
1959 // TODO(all): See DoCheckNonSmi for comments on use of tbz. 2000 // TODO(all): See DoCheckNonSmi for comments on use of tbz.
1960 DeoptimizeIfNotSmi(value, instr->environment()); 2001 DeoptimizeIfNotSmi(value, instr->environment());
1961 } 2002 }
1962 2003
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 2282
2242 2283
2243 void LCodeGen::DoConstantS(LConstantS* instr) { 2284 void LCodeGen::DoConstantS(LConstantS* instr) {
2244 __ Mov(ToRegister(instr->result()), Operand(instr->value())); 2285 __ Mov(ToRegister(instr->result()), Operand(instr->value()));
2245 } 2286 }
2246 2287
2247 2288
2248 void LCodeGen::DoConstantT(LConstantT* instr) { 2289 void LCodeGen::DoConstantT(LConstantT* instr) {
2249 Handle<Object> value = instr->value(); 2290 Handle<Object> value = instr->value();
2250 AllowDeferredHandleDereference smi_check; 2291 AllowDeferredHandleDereference smi_check;
2251 if (value->IsSmi()) { 2292 __ LoadObject(ToRegister(instr->result()), value);
2252 __ Mov(ToRegister(instr->result()), Operand(value));
2253 } else {
2254 __ LoadHeapObject(ToRegister(instr->result()),
2255 Handle<HeapObject>::cast(value));
2256 }
2257 } 2293 }
2258 2294
2259 2295
2260 void LCodeGen::DoContext(LContext* instr) { 2296 void LCodeGen::DoContext(LContext* instr) {
2261 // If there is a non-return use, the context must be moved to a register. 2297 // If there is a non-return use, the context must be moved to a register.
2262 Register result = ToRegister(instr->result()); 2298 Register result = ToRegister(instr->result());
2263 // TODO(jbramley): LContext is only generated if it meets this condition, so 2299 // TODO(jbramley): LContext is only generated if it meets this condition, so
2264 // why not move cp unconditionally? 2300 // why not move cp unconditionally?
2265 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) { 2301 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) {
2266 if (!it.value()->IsReturn()) { 2302 if (!it.value()->IsReturn()) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 __ Bind(&runtime); 2371 __ Bind(&runtime);
2336 __ Mov(x1, Operand(index)); 2372 __ Mov(x1, Operand(index));
2337 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 2373 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2338 } 2374 }
2339 2375
2340 __ Bind(&done); 2376 __ Bind(&done);
2341 } 2377 }
2342 2378
2343 2379
2344 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 2380 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
2345 if (instr->hydrogen_value()->IsSoftDeoptimize()) { 2381 Deoptimizer::BailoutType type = instr->hydrogen()->type();
2346 SoftDeoptimize(instr->environment()); 2382 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
2347 } else { 2383 // needed return address), even though the implementation of LAZY and EAGER is
2348 Deoptimize(instr->environment()); 2384 // now identical. When LAZY is eventually completely folded into EAGER, remove
2385 // the special case below.
2386 if (info()->IsStub() && (type == Deoptimizer::EAGER)) {
2387 type = Deoptimizer::LAZY;
2349 } 2388 }
2389 Deoptimize(instr->environment(), type);
2350 } 2390 }
2351 2391
2352 2392
2353 void LCodeGen::DoDivI(LDivI* instr) { 2393 void LCodeGen::DoDivI(LDivI* instr) {
2354 Register dividend = ToRegister32(instr->left()); 2394 Register dividend = ToRegister32(instr->left());
2355 Register result = ToRegister32(instr->result()); 2395 Register result = ToRegister32(instr->result());
2356 2396
2357 bool has_power_of_2_divisor = instr->hydrogen()->HasPowerOf2Divisor(); 2397 bool has_power_of_2_divisor = instr->hydrogen()->HasPowerOf2Divisor();
2358 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 2398 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
2359 bool bailout_on_minus_zero = 2399 bool bailout_on_minus_zero =
(...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after
3397 int offset = index * kPointerSize; 3437 int offset = index * kPointerSize;
3398 if (index < 0) { 3438 if (index < 0) {
3399 // Negative property indices are in-object properties, indexed from the 3439 // Negative property indices are in-object properties, indexed from the
3400 // end of the fixed part of the object. 3440 // end of the fixed part of the object.
3401 __ Ldr(result, FieldMemOperand(object, offset + type->instance_size())); 3441 __ Ldr(result, FieldMemOperand(object, offset + type->instance_size()));
3402 } else { 3442 } else {
3403 // Non-negative property indices are in the properties array. 3443 // Non-negative property indices are in the properties array.
3404 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 3444 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
3405 __ Ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize)); 3445 __ Ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
3406 } 3446 }
3407 } else if (lookup.IsConstantFunction()) { 3447 } else if (lookup.IsConstant()) {
3408 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); 3448 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
3409 __ LoadHeapObject(result, function); 3449 __ LoadObject(result, constant);
3410 } else { 3450 } else {
3411 // Negative lookup. Check prototypes. 3451 // Negative lookup. Check prototypes.
3412 Handle<HeapObject> current(HeapObject::cast((*type)->prototype())); 3452 Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
3413 Heap* heap = type->GetHeap(); 3453 Heap* heap = type->GetHeap();
3414 while (*current != heap->null_value()) { 3454 while (*current != heap->null_value()) {
3415 __ LoadHeapObject(result, current); 3455 __ LoadHeapObject(result, current);
3416 __ CompareMap(result, result, Handle<Map>(current->map())); 3456 __ CompareMap(result, result, Handle<Map>(current->map()));
3417 DeoptimizeIf(ne, env); 3457 DeoptimizeIf(ne, env);
3418 current = 3458 current =
3419 Handle<HeapObject>(HeapObject::cast(current->map()->prototype())); 3459 Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
3965 4005
3966 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 4006 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
3967 HMathMinMax::Operation op = instr->hydrogen()->operation(); 4007 HMathMinMax::Operation op = instr->hydrogen()->operation();
3968 if (instr->hydrogen()->representation().IsInteger32()) { 4008 if (instr->hydrogen()->representation().IsInteger32()) {
3969 Register result = ToRegister32(instr->result()); 4009 Register result = ToRegister32(instr->result());
3970 Register left = ToRegister32(instr->left()); 4010 Register left = ToRegister32(instr->left());
3971 Operand right = ToOperand32(instr->right()); 4011 Operand right = ToOperand32(instr->right());
3972 4012
3973 __ Cmp(left, right); 4013 __ Cmp(left, right);
3974 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le); 4014 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le);
4015 } else if (instr->hydrogen()->representation().IsSmi()) {
4016 Register result = ToRegister(instr->result());
4017 Register left = ToRegister(instr->left());
4018 Operand right = ToOperand(instr->right());
4019
4020 __ Cmp(left, right);
4021 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le);
3975 } else { 4022 } else {
3976 ASSERT(instr->hydrogen()->representation().IsDouble()); 4023 ASSERT(instr->hydrogen()->representation().IsDouble());
3977 DoubleRegister result = ToDoubleRegister(instr->result()); 4024 DoubleRegister result = ToDoubleRegister(instr->result());
3978 DoubleRegister left = ToDoubleRegister(instr->left()); 4025 DoubleRegister left = ToDoubleRegister(instr->left());
3979 DoubleRegister right = ToDoubleRegister(instr->right()); 4026 DoubleRegister right = ToDoubleRegister(instr->right());
3980 4027
3981 if (op == HMathMinMax::kMathMax) { 4028 if (op == HMathMinMax::kMathMax) {
3982 __ Fmax(result, left, right); 4029 __ Fmax(result, left, right);
3983 } else { 4030 } else {
3984 ASSERT(op == HMathMinMax::kMathMin); 4031 ASSERT(op == HMathMinMax::kMathMin);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4040 } else { 4087 } else {
4041 DeoptimizeIfNegative(dividend, instr->environment()); 4088 DeoptimizeIfNegative(dividend, instr->environment());
4042 } 4089 }
4043 } 4090 }
4044 } 4091 }
4045 __ Bind(&done); 4092 __ Bind(&done);
4046 } 4093 }
4047 4094
4048 4095
4049 void LCodeGen::DoMulConstI(LMulConstI* instr) { 4096 void LCodeGen::DoMulConstI(LMulConstI* instr) {
4097 // TODO(jbramley): Support smi operations (or make a separate DoMulConstS).
4098
4050 Register result = ToRegister32(instr->result()); 4099 Register result = ToRegister32(instr->result());
4051 Register left = ToRegister32(instr->left()); 4100 Register left = ToRegister32(instr->left());
4052 int32_t right = ToInteger32(instr->right()); 4101 int32_t right = ToInteger32(instr->right());
4053 4102
4054 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 4103 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
4055 bool bailout_on_minus_zero = 4104 bool bailout_on_minus_zero =
4056 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 4105 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
4057 4106
4058 if (bailout_on_minus_zero) { 4107 if (bailout_on_minus_zero) {
4059 if (right < 0) { 4108 if (right < 0) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
4132 } 4181 }
4133 } 4182 }
4134 break; 4183 break;
4135 } 4184 }
4136 } 4185 }
4137 4186
4138 4187
4139 void LCodeGen::DoMulI(LMulI* instr) { 4188 void LCodeGen::DoMulI(LMulI* instr) {
4140 Register result = ToRegister32(instr->result()); 4189 Register result = ToRegister32(instr->result());
4141 Register left = ToRegister32(instr->left()); 4190 Register left = ToRegister32(instr->left());
4191 Register right = ToRegister32(instr->right());
4142 4192
4143 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 4193 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
4144 bool bailout_on_minus_zero = 4194 bool bailout_on_minus_zero =
4145 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 4195 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
4146 4196
4147 Register right = ToRegister32(instr->right());
4148 if (bailout_on_minus_zero) { 4197 if (bailout_on_minus_zero) {
4149 // If one operand is zero and the other is negative, the result is -0. 4198 // If one operand is zero and the other is negative, the result is -0.
4150 // - Set Z (eq) if either left or right, or both, are 0. 4199 // - Set Z (eq) if either left or right, or both, are 0.
4151 __ Cmp(left, 0); 4200 __ Cmp(left, 0);
4152 __ Ccmp(right, 0, ZFlag, ne); 4201 __ Ccmp(right, 0, ZFlag, ne);
4153 // - If so (eq), set N (mi) if left + right is negative. 4202 // - If so (eq), set N (mi) if left + right is negative.
4154 // - Otherwise, clear N. 4203 // - Otherwise, clear N.
4155 __ Ccmn(left, right, NoFlag, eq); 4204 __ Ccmn(left, right, NoFlag, eq);
4156 DeoptimizeIf(mi, instr->environment()); 4205 DeoptimizeIf(mi, instr->environment());
4157 } 4206 }
4158 4207
4159 if (can_overflow) { 4208 if (can_overflow) {
4160 __ Smull(result.X(), left, right); 4209 __ Smull(result.X(), left, right);
4161 __ Cmp(result.X(), Operand(result, SXTW)); 4210 __ Cmp(result.X(), Operand(result, SXTW));
4162 DeoptimizeIf(ne, instr->environment()); 4211 DeoptimizeIf(ne, instr->environment());
4163 } else { 4212 } else {
4164 __ Mul(result, left, right); 4213 __ Mul(result, left, right);
4165 } 4214 }
4166 } 4215 }
4167 4216
4168 4217
4218 void LCodeGen::DoMulS(LMulS* instr) {
4219 Register result = ToRegister(instr->result());
4220 Register left = ToRegister(instr->left());
4221 Register right = ToRegister(instr->right());
4222
4223 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
4224 bool bailout_on_minus_zero =
4225 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
4226
4227 if (bailout_on_minus_zero) {
4228 // If one operand is zero and the other is negative, the result is -0.
4229 // - Set Z (eq) if either left or right, or both, are 0.
4230 __ Cmp(left, 0);
4231 __ Ccmp(right, 0, ZFlag, ne);
4232 // - If so (eq), set N (mi) if left + right is negative.
4233 // - Otherwise, clear N.
4234 __ Ccmn(left, right, NoFlag, eq);
4235 DeoptimizeIf(mi, instr->environment());
4236 }
4237
4238 STATIC_ASSERT((kSmiShift == 32) && (kSmiTag == 0));
4239 if (can_overflow) {
4240 __ Smulh(result, left, right);
4241 __ Cmp(result, Operand(result.W(), SXTW));
4242 __ SmiTag(result);
4243 DeoptimizeIf(ne, instr->environment());
4244 } else {
4245 // TODO(jbramley): This could be rewritten to support UseRegisterAtStart.
4246 ASSERT(!AreAliased(result, right));
4247 __ SmiUntag(result, left);
4248 __ Mul(result, result, right);
4249 }
4250 }
4251
4252
4169 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 4253 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4170 // TODO(3095996): Get rid of this. For now, we need to make the 4254 // TODO(3095996): Get rid of this. For now, we need to make the
4171 // result register contain a valid pointer because it is already 4255 // result register contain a valid pointer because it is already
4172 // contained in the register pointer map. 4256 // contained in the register pointer map.
4173 Register result = ToRegister(instr->result()); 4257 Register result = ToRegister(instr->result());
4174 __ Mov(result, 0); 4258 __ Mov(result, 0);
4175 4259
4176 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 4260 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4177 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 4261 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
4178 __ StoreToSafepointRegisterSlot(x0, result); 4262 __ StoreToSafepointRegisterSlot(x0, result);
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after
5262 CallRuntime(Runtime::kThrow, 1, instr); 5346 CallRuntime(Runtime::kThrow, 1, instr);
5263 5347
5264 if (FLAG_debug_code) { 5348 if (FLAG_debug_code) {
5265 __ Abort("Unreachable code in Throw."); 5349 __ Abort("Unreachable code in Throw.");
5266 } 5350 }
5267 } 5351 }
5268 5352
5269 5353
5270 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 5354 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
5271 Register object = ToRegister(instr->object()); 5355 Register object = ToRegister(instr->object());
5356 Register temp1 = ToRegister(instr->temp1());
5272 5357
5273 Handle<Map> from_map = instr->original_map(); 5358 Handle<Map> from_map = instr->original_map();
5274 Handle<Map> to_map = instr->transitioned_map(); 5359 Handle<Map> to_map = instr->transitioned_map();
5275 ElementsKind from_kind = instr->from_kind(); 5360 ElementsKind from_kind = instr->from_kind();
5276 ElementsKind to_kind = instr->to_kind(); 5361 ElementsKind to_kind = instr->to_kind();
5277 5362
5278 Register scratch;
5279 if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
5280 scratch = ToRegister(instr->temp1());
5281 } else {
5282 ASSERT(FLAG_compiled_transitions || instr->IsMarkedAsCall());
5283 scratch = x10;
5284 }
5285
5286 Label not_applicable; 5363 Label not_applicable;
5287 __ CompareMap(object, scratch, from_map); 5364 __ CheckMap(object, temp1, from_map, &not_applicable, DONT_DO_SMI_CHECK);
5288 __ B(ne, &not_applicable);
5289 5365
5290 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { 5366 if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
5291 Register new_map = ToRegister(instr->temp2()); 5367 Register new_map = ToRegister(instr->temp2());
5292 __ Mov(new_map, Operand(to_map)); 5368 __ Mov(new_map, Operand(to_map));
5293 __ Str(new_map, FieldMemOperand(object, HeapObject::kMapOffset)); 5369 __ Str(new_map, FieldMemOperand(object, HeapObject::kMapOffset));
5294 // Write barrier. 5370 // Write barrier.
5295 __ RecordWriteField(object, HeapObject::kMapOffset, new_map, scratch, 5371 __ RecordWriteField(object, HeapObject::kMapOffset, new_map, temp1,
5296 GetLinkRegisterState(), kDontSaveFPRegs); 5372 GetLinkRegisterState(), kDontSaveFPRegs);
5297 } else if (FLAG_compiled_transitions) { 5373 } else {
5298 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 5374 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
5299 __ Mov(x0, object); 5375 __ Mov(x0, object);
5300 __ Mov(x1, Operand(to_map)); 5376 __ Mov(x1, Operand(to_map));
5301 TransitionElementsKindStub stub(from_kind, to_kind); 5377 TransitionElementsKindStub stub(from_kind, to_kind);
5302 __ CallStub(&stub); 5378 __ CallStub(&stub);
5303 RecordSafepointWithRegisters( 5379 RecordSafepointWithRegisters(
5304 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 5380 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5305 } else if ((IsFastSmiElementsKind(from_kind) &&
5306 IsFastDoubleElementsKind(to_kind)) ||
5307 (IsFastDoubleElementsKind(from_kind) &&
5308 IsFastObjectElementsKind(to_kind))) {
5309 ASSERT((instr->temp1() == NULL) && (instr->temp2() == NULL));
5310 __ Mov(x2, object);
5311 __ Mov(x3, Operand(to_map));
5312 if (IsFastSmiElementsKind(from_kind)) {
5313 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
5314 RelocInfo::CODE_TARGET, instr);
5315 } else if (IsFastDoubleElementsKind(from_kind)) {
5316 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
5317 RelocInfo::CODE_TARGET, instr);
5318 }
5319 } else {
5320 UNREACHABLE();
5321 } 5381 }
5322 __ Bind(&not_applicable); 5382 __ Bind(&not_applicable);
5323 } 5383 }
5324 5384
5325 5385
5326 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 5386 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
5327 Register object = ToRegister(instr->object()); 5387 Register object = ToRegister(instr->object());
5328 Register temp1 = ToRegister(instr->temp1()); 5388 Register temp1 = ToRegister(instr->temp1());
5329 Register temp2 = ToRegister(instr->temp2()); 5389 Register temp2 = ToRegister(instr->temp2());
5330 __ TestJSArrayForAllocationMemento(object, temp1, temp2); 5390 __ TestJSArrayForAllocationMemento(object, temp1, temp2);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
5546 __ Bind(&out_of_object); 5606 __ Bind(&out_of_object);
5547 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 5607 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
5548 // Index is equal to negated out of object property index plus 1. 5608 // Index is equal to negated out of object property index plus 1.
5549 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); 5609 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2));
5550 __ Ldr(result, FieldMemOperand(result, 5610 __ Ldr(result, FieldMemOperand(result,
5551 FixedArray::kHeaderSize - kPointerSize)); 5611 FixedArray::kHeaderSize - kPointerSize));
5552 __ Bind(&done); 5612 __ Bind(&done);
5553 } 5613 }
5554 5614
5555 } } // namespace v8::internal 5615 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-codegen-a64.h ('k') | src/a64/macro-assembler-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698