| 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/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 #ifdef DEBUG | 116 #ifdef DEBUG |
| 117 if (strlen(FLAG_stop_at) > 0 && | 117 if (strlen(FLAG_stop_at) > 0 && |
| 118 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 118 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 119 __ stop("stop-at"); | 119 __ stop("stop-at"); |
| 120 } | 120 } |
| 121 #endif | 121 #endif |
| 122 | 122 |
| 123 // Sloppy mode functions and builtins need to replace the receiver with the | 123 // Sloppy mode functions and builtins need to replace the receiver with the |
| 124 // global proxy when called as functions (without an explicit receiver | 124 // global proxy when called as functions (without an explicit receiver |
| 125 // object). | 125 // object). |
| 126 if (info->strict_mode() == SLOPPY && !info->is_native()) { | 126 if (is_sloppy(info->language_mode()) && !info->is_native()) { |
| 127 Label ok; | 127 Label ok; |
| 128 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 128 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
| 129 __ LoadP(r5, MemOperand(sp, receiver_offset), r0); | 129 __ LoadP(r5, MemOperand(sp, receiver_offset), r0); |
| 130 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); | 130 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); |
| 131 __ bne(&ok); | 131 __ bne(&ok); |
| 132 | 132 |
| 133 __ LoadP(r5, GlobalObjectOperand()); | 133 __ LoadP(r5, GlobalObjectOperand()); |
| 134 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); | 134 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); |
| 135 | 135 |
| 136 __ StoreP(r5, MemOperand(sp, receiver_offset), r0); | 136 __ StoreP(r5, MemOperand(sp, receiver_offset), r0); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 int offset = num_parameters * kPointerSize; | 260 int offset = num_parameters * kPointerSize; |
| 261 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 261 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
| 262 __ LoadSmiLiteral(r4, Smi::FromInt(num_parameters)); | 262 __ LoadSmiLiteral(r4, Smi::FromInt(num_parameters)); |
| 263 __ Push(r6, r5, r4); | 263 __ Push(r6, r5, r4); |
| 264 | 264 |
| 265 // Arguments to ArgumentsAccessStub: | 265 // Arguments to ArgumentsAccessStub: |
| 266 // function, receiver address, parameter count. | 266 // function, receiver address, parameter count. |
| 267 // The stub will rewrite receiever and parameter count if the previous | 267 // The stub will rewrite receiever and parameter count if the previous |
| 268 // stack frame was an arguments adapter frame. | 268 // stack frame was an arguments adapter frame. |
| 269 ArgumentsAccessStub::Type type; | 269 ArgumentsAccessStub::Type type; |
| 270 if (strict_mode() == STRICT) { | 270 if (is_strict(language_mode())) { |
| 271 type = ArgumentsAccessStub::NEW_STRICT; | 271 type = ArgumentsAccessStub::NEW_STRICT; |
| 272 } else if (function()->has_duplicate_parameters()) { | 272 } else if (function()->has_duplicate_parameters()) { |
| 273 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; | 273 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
| 274 } else { | 274 } else { |
| 275 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; | 275 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
| 276 } | 276 } |
| 277 ArgumentsAccessStub stub(isolate(), type); | 277 ArgumentsAccessStub stub(isolate(), type); |
| 278 __ CallStub(&stub); | 278 __ CallStub(&stub); |
| 279 | 279 |
| 280 SetVar(arguments, r3, r4, r5); | 280 SetVar(arguments, r3, r4, r5); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 Comment cmnt(masm_, "[ ForInStatement"); | 1059 Comment cmnt(masm_, "[ ForInStatement"); |
| 1060 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 1060 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
| 1061 SetStatementPosition(stmt); | 1061 SetStatementPosition(stmt); |
| 1062 | 1062 |
| 1063 Label loop, exit; | 1063 Label loop, exit; |
| 1064 ForIn loop_statement(this, stmt); | 1064 ForIn loop_statement(this, stmt); |
| 1065 increment_loop_depth(); | 1065 increment_loop_depth(); |
| 1066 | 1066 |
| 1067 // Get the object to enumerate over. If the object is null or undefined, skip | 1067 // Get the object to enumerate over. If the object is null or undefined, skip |
| 1068 // over the loop. See ECMA-262 version 5, section 12.6.4. | 1068 // over the loop. See ECMA-262 version 5, section 12.6.4. |
| 1069 SetExpressionPosition(stmt->enumerable()); |
| 1069 VisitForAccumulatorValue(stmt->enumerable()); | 1070 VisitForAccumulatorValue(stmt->enumerable()); |
| 1070 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1071 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 1071 __ cmp(r3, ip); | 1072 __ cmp(r3, ip); |
| 1072 __ beq(&exit); | 1073 __ beq(&exit); |
| 1073 Register null_value = r7; | 1074 Register null_value = r7; |
| 1074 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 1075 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 1075 __ cmp(r3, null_value); | 1076 __ cmp(r3, null_value); |
| 1076 __ beq(&exit); | 1077 __ beq(&exit); |
| 1077 | 1078 |
| 1078 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); | 1079 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 __ LoadSmiLiteral(r4, Smi::FromInt(0)); // Zero indicates proxy | 1165 __ LoadSmiLiteral(r4, Smi::FromInt(0)); // Zero indicates proxy |
| 1165 __ bind(&non_proxy); | 1166 __ bind(&non_proxy); |
| 1166 __ Push(r4, r3); // Smi and array | 1167 __ Push(r4, r3); // Smi and array |
| 1167 __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 1168 __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
| 1168 __ LoadSmiLiteral(r3, Smi::FromInt(0)); | 1169 __ LoadSmiLiteral(r3, Smi::FromInt(0)); |
| 1169 __ Push(r4, r3); // Fixed array length (as smi) and initial index. | 1170 __ Push(r4, r3); // Fixed array length (as smi) and initial index. |
| 1170 | 1171 |
| 1171 // Generate code for doing the condition check. | 1172 // Generate code for doing the condition check. |
| 1172 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 1173 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
| 1173 __ bind(&loop); | 1174 __ bind(&loop); |
| 1175 SetExpressionPosition(stmt->each()); |
| 1176 |
| 1174 // Load the current count to r3, load the length to r4. | 1177 // Load the current count to r3, load the length to r4. |
| 1175 __ LoadP(r3, MemOperand(sp, 0 * kPointerSize)); | 1178 __ LoadP(r3, MemOperand(sp, 0 * kPointerSize)); |
| 1176 __ LoadP(r4, MemOperand(sp, 1 * kPointerSize)); | 1179 __ LoadP(r4, MemOperand(sp, 1 * kPointerSize)); |
| 1177 __ cmpl(r3, r4); // Compare to the array length. | 1180 __ cmpl(r3, r4); // Compare to the array length. |
| 1178 __ bge(loop_statement.break_label()); | 1181 __ bge(loop_statement.break_label()); |
| 1179 | 1182 |
| 1180 // Get the current entry of the array into register r6. | 1183 // Get the current entry of the array into register r6. |
| 1181 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); | 1184 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); |
| 1182 __ addi(r5, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1185 __ addi(r5, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1183 __ SmiToPtrArrayOffset(r6, r3); | 1186 __ SmiToPtrArrayOffset(r6, r3); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 __ bind(loop_statement.break_label()); | 1240 __ bind(loop_statement.break_label()); |
| 1238 __ Drop(5); | 1241 __ Drop(5); |
| 1239 | 1242 |
| 1240 // Exit and decrement the loop depth. | 1243 // Exit and decrement the loop depth. |
| 1241 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1244 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1242 __ bind(&exit); | 1245 __ bind(&exit); |
| 1243 decrement_loop_depth(); | 1246 decrement_loop_depth(); |
| 1244 } | 1247 } |
| 1245 | 1248 |
| 1246 | 1249 |
| 1247 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | |
| 1248 Comment cmnt(masm_, "[ ForOfStatement"); | |
| 1249 SetStatementPosition(stmt); | |
| 1250 | |
| 1251 Iteration loop_statement(this, stmt); | |
| 1252 increment_loop_depth(); | |
| 1253 | |
| 1254 // var iterator = iterable[Symbol.iterator](); | |
| 1255 VisitForEffect(stmt->assign_iterator()); | |
| 1256 | |
| 1257 // Loop entry. | |
| 1258 __ bind(loop_statement.continue_label()); | |
| 1259 | |
| 1260 // result = iterator.next() | |
| 1261 VisitForEffect(stmt->next_result()); | |
| 1262 | |
| 1263 // if (result.done) break; | |
| 1264 Label result_not_done; | |
| 1265 VisitForControl(stmt->result_done(), loop_statement.break_label(), | |
| 1266 &result_not_done, &result_not_done); | |
| 1267 __ bind(&result_not_done); | |
| 1268 | |
| 1269 // each = result.value | |
| 1270 VisitForEffect(stmt->assign_each()); | |
| 1271 | |
| 1272 // Generate code for the body of the loop. | |
| 1273 Visit(stmt->body()); | |
| 1274 | |
| 1275 // Check stack before looping. | |
| 1276 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | |
| 1277 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); | |
| 1278 __ b(loop_statement.continue_label()); | |
| 1279 | |
| 1280 // Exit and decrement the loop depth. | |
| 1281 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | |
| 1282 __ bind(loop_statement.break_label()); | |
| 1283 decrement_loop_depth(); | |
| 1284 } | |
| 1285 | |
| 1286 | |
| 1287 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1250 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
| 1288 bool pretenure) { | 1251 bool pretenure) { |
| 1289 // Use the fast case closure allocation code that allocates in new | 1252 // Use the fast case closure allocation code that allocates in new |
| 1290 // space for nested functions that don't need literals cloning. If | 1253 // space for nested functions that don't need literals cloning. If |
| 1291 // we're running with the --always-opt or the --prepare-always-opt | 1254 // we're running with the --always-opt or the --prepare-always-opt |
| 1292 // flag, we need to use the runtime function so that the new function | 1255 // flag, we need to use the runtime function so that the new function |
| 1293 // we are creating here gets a chance to have its code optimized and | 1256 // we are creating here gets a chance to have its code optimized and |
| 1294 // doesn't just get a copy of the existing unoptimized code. | 1257 // doesn't just get a copy of the existing unoptimized code. |
| 1295 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && | 1258 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && |
| 1296 scope()->is_function_scope() && info->num_literals() == 0) { | 1259 scope()->is_function_scope() && info->num_literals() == 0) { |
| 1297 FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); | 1260 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
| 1298 __ mov(r5, Operand(info)); | 1261 __ mov(r5, Operand(info)); |
| 1299 __ CallStub(&stub); | 1262 __ CallStub(&stub); |
| 1300 } else { | 1263 } else { |
| 1301 __ mov(r3, Operand(info)); | 1264 __ mov(r3, Operand(info)); |
| 1302 __ LoadRoot( | 1265 __ LoadRoot( |
| 1303 r4, pretenure ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 1266 r4, pretenure ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
| 1304 __ Push(cp, r3, r4); | 1267 __ Push(cp, r3, r4); |
| 1305 __ CallRuntime(Runtime::kNewClosure, 3); | 1268 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1306 } | 1269 } |
| 1307 context()->Plug(r3); | 1270 context()->Plug(r3); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1332 } | 1295 } |
| 1333 | 1296 |
| 1334 __ Cmpi(r3, Operand(isolate()->factory()->undefined_value()), r0); | 1297 __ Cmpi(r3, Operand(isolate()->factory()->undefined_value()), r0); |
| 1335 Label done; | 1298 Label done; |
| 1336 __ bne(&done); | 1299 __ bne(&done); |
| 1337 __ CallRuntime(Runtime::kThrowNonMethodError, 0); | 1300 __ CallRuntime(Runtime::kThrowNonMethodError, 0); |
| 1338 __ bind(&done); | 1301 __ bind(&done); |
| 1339 } | 1302 } |
| 1340 | 1303 |
| 1341 | 1304 |
| 1305 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
| 1306 int offset) { |
| 1307 if (NeedsHomeObject(initializer)) { |
| 1308 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1309 __ mov(StoreDescriptor::NameRegister(), |
| 1310 Operand(isolate()->factory()->home_object_symbol())); |
| 1311 __ LoadP(StoreDescriptor::ValueRegister(), |
| 1312 MemOperand(sp, offset * kPointerSize)); |
| 1313 CallStoreIC(); |
| 1314 } |
| 1315 } |
| 1316 |
| 1317 |
| 1342 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | 1318 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, |
| 1343 TypeofState typeof_state, | 1319 TypeofState typeof_state, |
| 1344 Label* slow) { | 1320 Label* slow) { |
| 1345 Register current = cp; | 1321 Register current = cp; |
| 1346 Register next = r4; | 1322 Register next = r4; |
| 1347 Register temp = r5; | 1323 Register temp = r5; |
| 1348 | 1324 |
| 1349 Scope* s = scope(); | 1325 Scope* s = scope(); |
| 1350 while (s != NULL) { | 1326 while (s != NULL) { |
| 1351 if (s->num_heap_slots() > 0) { | 1327 if (s->num_heap_slots() > 0) { |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 // if (false) { const x; }; var y = x; | 1486 // if (false) { const x; }; var y = x; |
| 1511 // | 1487 // |
| 1512 // The condition on the declaration scopes is a conservative check for | 1488 // The condition on the declaration scopes is a conservative check for |
| 1513 // nested functions that access a binding and are called before the | 1489 // nested functions that access a binding and are called before the |
| 1514 // binding is initialized: | 1490 // binding is initialized: |
| 1515 // function() { f(); let x = 1; function f() { x = 2; } } | 1491 // function() { f(); let x = 1; function f() { x = 2; } } |
| 1516 // | 1492 // |
| 1517 bool skip_init_check; | 1493 bool skip_init_check; |
| 1518 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1494 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
| 1519 skip_init_check = false; | 1495 skip_init_check = false; |
| 1496 } else if (var->is_this()) { |
| 1497 CHECK(info_->function() != nullptr && |
| 1498 (info_->function()->kind() & kSubclassConstructor) != 0); |
| 1499 // TODO(dslomov): implement 'this' hole check elimination. |
| 1500 skip_init_check = false; |
| 1520 } else { | 1501 } else { |
| 1521 // Check that we always have valid source position. | 1502 // Check that we always have valid source position. |
| 1522 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); | 1503 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
| 1523 DCHECK(proxy->position() != RelocInfo::kNoPosition); | 1504 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
| 1524 skip_init_check = var->mode() != CONST_LEGACY && | 1505 skip_init_check = var->mode() != CONST_LEGACY && |
| 1525 var->initializer_position() < proxy->position(); | 1506 var->initializer_position() < proxy->position(); |
| 1526 } | 1507 } |
| 1527 | 1508 |
| 1528 if (!skip_init_check) { | 1509 if (!skip_init_check) { |
| 1529 Label done; | 1510 Label done; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 // If result_saved is true the result is on top of the stack. If | 1638 // If result_saved is true the result is on top of the stack. If |
| 1658 // result_saved is false the result is in r3. | 1639 // result_saved is false the result is in r3. |
| 1659 bool result_saved = false; | 1640 bool result_saved = false; |
| 1660 | 1641 |
| 1661 // Mark all computed expressions that are bound to a key that | 1642 // Mark all computed expressions that are bound to a key that |
| 1662 // is shadowed by a later occurrence of the same key. For the | 1643 // is shadowed by a later occurrence of the same key. For the |
| 1663 // marked expressions, no store code is emitted. | 1644 // marked expressions, no store code is emitted. |
| 1664 expr->CalculateEmitStore(zone()); | 1645 expr->CalculateEmitStore(zone()); |
| 1665 | 1646 |
| 1666 AccessorTable accessor_table(zone()); | 1647 AccessorTable accessor_table(zone()); |
| 1667 for (int i = 0; i < expr->properties()->length(); i++) { | 1648 int property_index = 0; |
| 1668 ObjectLiteral::Property* property = expr->properties()->at(i); | 1649 for (; property_index < expr->properties()->length(); property_index++) { |
| 1650 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1651 if (property->is_computed_name()) break; |
| 1669 if (property->IsCompileTimeValue()) continue; | 1652 if (property->IsCompileTimeValue()) continue; |
| 1670 | 1653 |
| 1671 Literal* key = property->key(); | 1654 Literal* key = property->key()->AsLiteral(); |
| 1672 Expression* value = property->value(); | 1655 Expression* value = property->value(); |
| 1673 if (!result_saved) { | 1656 if (!result_saved) { |
| 1674 __ push(r3); // Save result on stack | 1657 __ push(r3); // Save result on stack |
| 1675 result_saved = true; | 1658 result_saved = true; |
| 1676 } | 1659 } |
| 1677 switch (property->kind()) { | 1660 switch (property->kind()) { |
| 1678 case ObjectLiteral::Property::CONSTANT: | 1661 case ObjectLiteral::Property::CONSTANT: |
| 1679 UNREACHABLE(); | 1662 UNREACHABLE(); |
| 1680 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1663 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1681 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1664 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1682 // Fall through. | 1665 // Fall through. |
| 1683 case ObjectLiteral::Property::COMPUTED: | 1666 case ObjectLiteral::Property::COMPUTED: |
| 1684 // It is safe to use [[Put]] here because the boilerplate already | 1667 // It is safe to use [[Put]] here because the boilerplate already |
| 1685 // contains computed properties with an uninitialized value. | 1668 // contains computed properties with an uninitialized value. |
| 1686 if (key->value()->IsInternalizedString()) { | 1669 if (key->value()->IsInternalizedString()) { |
| 1687 if (property->emit_store()) { | 1670 if (property->emit_store()) { |
| 1688 VisitForAccumulatorValue(value); | 1671 VisitForAccumulatorValue(value); |
| 1689 DCHECK(StoreDescriptor::ValueRegister().is(r3)); | 1672 DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
| 1690 __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); | 1673 __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); |
| 1691 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1674 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1692 CallStoreIC(key->LiteralFeedbackId()); | 1675 CallStoreIC(key->LiteralFeedbackId()); |
| 1693 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1676 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1677 |
| 1678 if (NeedsHomeObject(value)) { |
| 1679 __ Move(StoreDescriptor::ReceiverRegister(), r3); |
| 1680 __ mov(StoreDescriptor::NameRegister(), |
| 1681 Operand(isolate()->factory()->home_object_symbol())); |
| 1682 __ LoadP(StoreDescriptor::ValueRegister(), MemOperand(sp)); |
| 1683 CallStoreIC(); |
| 1684 } |
| 1694 } else { | 1685 } else { |
| 1695 VisitForEffect(value); | 1686 VisitForEffect(value); |
| 1696 } | 1687 } |
| 1697 break; | 1688 break; |
| 1698 } | 1689 } |
| 1699 // Duplicate receiver on stack. | 1690 // Duplicate receiver on stack. |
| 1700 __ LoadP(r3, MemOperand(sp)); | 1691 __ LoadP(r3, MemOperand(sp)); |
| 1701 __ push(r3); | 1692 __ push(r3); |
| 1702 VisitForStackValue(key); | 1693 VisitForStackValue(key); |
| 1703 VisitForStackValue(value); | 1694 VisitForStackValue(value); |
| 1704 if (property->emit_store()) { | 1695 if (property->emit_store()) { |
| 1696 EmitSetHomeObjectIfNeeded(value, 2); |
| 1705 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes | 1697 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes |
| 1706 __ push(r3); | 1698 __ push(r3); |
| 1707 __ CallRuntime(Runtime::kSetProperty, 4); | 1699 __ CallRuntime(Runtime::kSetProperty, 4); |
| 1708 } else { | 1700 } else { |
| 1709 __ Drop(3); | 1701 __ Drop(3); |
| 1710 } | 1702 } |
| 1711 break; | 1703 break; |
| 1712 case ObjectLiteral::Property::PROTOTYPE: | 1704 case ObjectLiteral::Property::PROTOTYPE: |
| 1713 // Duplicate receiver on stack. | 1705 // Duplicate receiver on stack. |
| 1714 __ LoadP(r3, MemOperand(sp)); | 1706 __ LoadP(r3, MemOperand(sp)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1731 } | 1723 } |
| 1732 | 1724 |
| 1733 // Emit code to define accessors, using only a single call to the runtime for | 1725 // Emit code to define accessors, using only a single call to the runtime for |
| 1734 // each pair of corresponding getters and setters. | 1726 // each pair of corresponding getters and setters. |
| 1735 for (AccessorTable::Iterator it = accessor_table.begin(); | 1727 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1736 it != accessor_table.end(); ++it) { | 1728 it != accessor_table.end(); ++it) { |
| 1737 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. | 1729 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
| 1738 __ push(r3); | 1730 __ push(r3); |
| 1739 VisitForStackValue(it->first); | 1731 VisitForStackValue(it->first); |
| 1740 EmitAccessor(it->second->getter); | 1732 EmitAccessor(it->second->getter); |
| 1733 EmitSetHomeObjectIfNeeded(it->second->getter, 2); |
| 1741 EmitAccessor(it->second->setter); | 1734 EmitAccessor(it->second->setter); |
| 1735 EmitSetHomeObjectIfNeeded(it->second->setter, 3); |
| 1742 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); | 1736 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
| 1743 __ push(r3); | 1737 __ push(r3); |
| 1744 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1738 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
| 1745 } | 1739 } |
| 1746 | 1740 |
| 1741 // Object literals have two parts. The "static" part on the left contains no |
| 1742 // computed property names, and so we can compute its map ahead of time; see |
| 1743 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1744 // starts with the first computed property name, and continues with all |
| 1745 // properties to its right. All the code from above initializes the static |
| 1746 // component of the object literal, and arranges for the map of the result to |
| 1747 // reflect the static order in which the keys appear. For the dynamic |
| 1748 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1749 // calls. This will preserve insertion order. |
| 1750 for (; property_index < expr->properties()->length(); property_index++) { |
| 1751 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1752 |
| 1753 Expression* value = property->value(); |
| 1754 if (!result_saved) { |
| 1755 __ push(r3); // Save result on the stack |
| 1756 result_saved = true; |
| 1757 } |
| 1758 |
| 1759 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
| 1760 __ push(r3); |
| 1761 |
| 1762 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1763 DCHECK(!property->is_computed_name()); |
| 1764 VisitForStackValue(value); |
| 1765 DCHECK(property->emit_store()); |
| 1766 __ CallRuntime(Runtime::kInternalSetPrototype, 2); |
| 1767 } else { |
| 1768 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
| 1769 VisitForStackValue(value); |
| 1770 |
| 1771 switch (property->kind()) { |
| 1772 case ObjectLiteral::Property::CONSTANT: |
| 1773 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1774 case ObjectLiteral::Property::COMPUTED: |
| 1775 if (property->emit_store()) { |
| 1776 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
| 1777 __ push(r3); |
| 1778 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
| 1779 } else { |
| 1780 __ Drop(3); |
| 1781 } |
| 1782 break; |
| 1783 |
| 1784 case ObjectLiteral::Property::PROTOTYPE: |
| 1785 UNREACHABLE(); |
| 1786 break; |
| 1787 |
| 1788 case ObjectLiteral::Property::GETTER: |
| 1789 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1790 __ push(r3); |
| 1791 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
| 1792 break; |
| 1793 |
| 1794 case ObjectLiteral::Property::SETTER: |
| 1795 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1796 __ push(r3); |
| 1797 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
| 1798 break; |
| 1799 } |
| 1800 } |
| 1801 } |
| 1802 |
| 1747 if (expr->has_function()) { | 1803 if (expr->has_function()) { |
| 1748 DCHECK(result_saved); | 1804 DCHECK(result_saved); |
| 1749 __ LoadP(r3, MemOperand(sp)); | 1805 __ LoadP(r3, MemOperand(sp)); |
| 1750 __ push(r3); | 1806 __ push(r3); |
| 1751 __ CallRuntime(Runtime::kToFastProperties, 1); | 1807 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1752 } | 1808 } |
| 1753 | 1809 |
| 1754 if (result_saved) { | 1810 if (result_saved) { |
| 1755 context()->PlugTOS(); | 1811 context()->PlugTOS(); |
| 1756 } else { | 1812 } else { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1927 EmitKeyedPropertyLoad(property); | 1983 EmitKeyedPropertyLoad(property); |
| 1928 PrepareForBailoutForId(property->LoadId(), TOS_REG); | 1984 PrepareForBailoutForId(property->LoadId(), TOS_REG); |
| 1929 break; | 1985 break; |
| 1930 } | 1986 } |
| 1931 } | 1987 } |
| 1932 | 1988 |
| 1933 Token::Value op = expr->binary_op(); | 1989 Token::Value op = expr->binary_op(); |
| 1934 __ push(r3); // Left operand goes on the stack. | 1990 __ push(r3); // Left operand goes on the stack. |
| 1935 VisitForAccumulatorValue(expr->value()); | 1991 VisitForAccumulatorValue(expr->value()); |
| 1936 | 1992 |
| 1937 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | |
| 1938 ? OVERWRITE_RIGHT | |
| 1939 : NO_OVERWRITE; | |
| 1940 SetSourcePosition(expr->position() + 1); | 1993 SetSourcePosition(expr->position() + 1); |
| 1941 AccumulatorValueContext context(this); | 1994 AccumulatorValueContext context(this); |
| 1942 if (ShouldInlineSmiCase(op)) { | 1995 if (ShouldInlineSmiCase(op)) { |
| 1943 EmitInlineSmiBinaryOp(expr->binary_operation(), op, mode, expr->target(), | 1996 EmitInlineSmiBinaryOp(expr->binary_operation(), op, expr->target(), |
| 1944 expr->value()); | 1997 expr->value()); |
| 1945 } else { | 1998 } else { |
| 1946 EmitBinaryOp(expr->binary_operation(), op, mode); | 1999 EmitBinaryOp(expr->binary_operation(), op); |
| 1947 } | 2000 } |
| 1948 | 2001 |
| 1949 // Deoptimization point in case the binary operation may have side effects. | 2002 // Deoptimization point in case the binary operation may have side effects. |
| 1950 PrepareForBailout(expr->binary_operation(), TOS_REG); | 2003 PrepareForBailout(expr->binary_operation(), TOS_REG); |
| 1951 } else { | 2004 } else { |
| 1952 VisitForAccumulatorValue(expr->value()); | 2005 VisitForAccumulatorValue(expr->value()); |
| 1953 } | 2006 } |
| 1954 | 2007 |
| 1955 // Record source position before possible IC call. | 2008 // Record source position before possible IC call. |
| 1956 SetSourcePosition(expr->position()); | 2009 SetSourcePosition(expr->position()); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 Expression* generator, Expression* value, | 2205 Expression* generator, Expression* value, |
| 2153 JSGeneratorObject::ResumeMode resume_mode) { | 2206 JSGeneratorObject::ResumeMode resume_mode) { |
| 2154 // The value stays in r3, and is ultimately read by the resumed generator, as | 2207 // The value stays in r3, and is ultimately read by the resumed generator, as |
| 2155 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 2208 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 2156 // is read to throw the value when the resumed generator is already closed. | 2209 // is read to throw the value when the resumed generator is already closed. |
| 2157 // r4 will hold the generator object until the activation has been resumed. | 2210 // r4 will hold the generator object until the activation has been resumed. |
| 2158 VisitForStackValue(generator); | 2211 VisitForStackValue(generator); |
| 2159 VisitForAccumulatorValue(value); | 2212 VisitForAccumulatorValue(value); |
| 2160 __ pop(r4); | 2213 __ pop(r4); |
| 2161 | 2214 |
| 2162 // Check generator state. | |
| 2163 Label wrong_state, closed_state, done; | |
| 2164 __ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset)); | |
| 2165 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | |
| 2166 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | |
| 2167 __ CmpSmiLiteral(r6, Smi::FromInt(0), r0); | |
| 2168 __ beq(&closed_state); | |
| 2169 __ blt(&wrong_state); | |
| 2170 | |
| 2171 // Load suspended function and context. | 2215 // Load suspended function and context. |
| 2172 __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset)); | 2216 __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset)); |
| 2173 __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset)); | 2217 __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset)); |
| 2174 | 2218 |
| 2175 // Load receiver and store as the first argument. | 2219 // Load receiver and store as the first argument. |
| 2176 __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset)); | 2220 __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset)); |
| 2177 __ push(r5); | 2221 __ push(r5); |
| 2178 | 2222 |
| 2179 // Push holes for the rest of the arguments to the generator function. | 2223 // Push holes for the rest of the arguments to the generator function. |
| 2180 __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset)); | 2224 __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset)); |
| 2181 __ LoadWordArith( | 2225 __ LoadWordArith( |
| 2182 r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); | 2226 r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 2183 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); | 2227 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2184 Label argument_loop, push_frame; | 2228 Label argument_loop, push_frame; |
| 2185 #if V8_TARGET_ARCH_PPC64 | 2229 #if V8_TARGET_ARCH_PPC64 |
| 2186 __ cmpi(r6, Operand::Zero()); | 2230 __ cmpi(r6, Operand::Zero()); |
| 2187 __ beq(&push_frame); | 2231 __ beq(&push_frame); |
| 2188 #else | 2232 #else |
| 2189 __ SmiUntag(r6, SetRC); | 2233 __ SmiUntag(r6, SetRC); |
| 2190 __ beq(&push_frame, cr0); | 2234 __ beq(&push_frame, cr0); |
| 2191 #endif | 2235 #endif |
| 2192 __ mtctr(r6); | 2236 __ mtctr(r6); |
| 2193 __ bind(&argument_loop); | 2237 __ bind(&argument_loop); |
| 2194 __ push(r5); | 2238 __ push(r5); |
| 2195 __ bdnz(&argument_loop); | 2239 __ bdnz(&argument_loop); |
| 2196 | 2240 |
| 2197 // Enter a new JavaScript frame, and initialize its slots as they were when | 2241 // Enter a new JavaScript frame, and initialize its slots as they were when |
| 2198 // the generator was suspended. | 2242 // the generator was suspended. |
| 2199 Label resume_frame; | 2243 Label resume_frame, done; |
| 2200 __ bind(&push_frame); | 2244 __ bind(&push_frame); |
| 2201 __ b(&resume_frame, SetLK); | 2245 __ b(&resume_frame, SetLK); |
| 2202 __ b(&done); | 2246 __ b(&done); |
| 2203 __ bind(&resume_frame); | 2247 __ bind(&resume_frame); |
| 2204 // lr = return address. | 2248 // lr = return address. |
| 2205 // fp = caller's frame pointer. | 2249 // fp = caller's frame pointer. |
| 2206 // cp = callee's context, | 2250 // cp = callee's context, |
| 2207 // r7 = callee's JS function. | 2251 // r7 = callee's JS function. |
| 2208 __ PushFixedFrame(r7); | 2252 __ PushFixedFrame(r7); |
| 2209 // Adjust FP to point to saved FP. | 2253 // Adjust FP to point to saved FP. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 __ bdnz(&operand_loop); | 2297 __ bdnz(&operand_loop); |
| 2254 | 2298 |
| 2255 __ bind(&call_resume); | 2299 __ bind(&call_resume); |
| 2256 DCHECK(!result_register().is(r4)); | 2300 DCHECK(!result_register().is(r4)); |
| 2257 __ Push(r4, result_register()); | 2301 __ Push(r4, result_register()); |
| 2258 __ Push(Smi::FromInt(resume_mode)); | 2302 __ Push(Smi::FromInt(resume_mode)); |
| 2259 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2303 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2260 // Not reached: the runtime call returns elsewhere. | 2304 // Not reached: the runtime call returns elsewhere. |
| 2261 __ stop("not-reached"); | 2305 __ stop("not-reached"); |
| 2262 | 2306 |
| 2263 // Reach here when generator is closed. | |
| 2264 __ bind(&closed_state); | |
| 2265 if (resume_mode == JSGeneratorObject::NEXT) { | |
| 2266 // Return completed iterator result when generator is closed. | |
| 2267 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | |
| 2268 __ push(r5); | |
| 2269 // Pop value from top-of-stack slot; box result into result register. | |
| 2270 EmitCreateIteratorResult(true); | |
| 2271 } else { | |
| 2272 // Throw the provided value. | |
| 2273 __ push(r3); | |
| 2274 __ CallRuntime(Runtime::kThrow, 1); | |
| 2275 } | |
| 2276 __ b(&done); | |
| 2277 | |
| 2278 // Throw error if we attempt to operate on a running generator. | |
| 2279 __ bind(&wrong_state); | |
| 2280 __ push(r4); | |
| 2281 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | |
| 2282 | |
| 2283 __ bind(&done); | 2307 __ bind(&done); |
| 2284 context()->Plug(result_register()); | 2308 context()->Plug(result_register()); |
| 2285 } | 2309 } |
| 2286 | 2310 |
| 2287 | 2311 |
| 2288 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2312 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 2289 Label gc_required; | 2313 Label gc_required; |
| 2290 Label allocated; | 2314 Label allocated; |
| 2291 | 2315 |
| 2292 const int instance_size = 5 * kPointerSize; | 2316 const int instance_size = 5 * kPointerSize; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2370 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2394 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| 2371 // Stack: receiver, home_object, key. | 2395 // Stack: receiver, home_object, key. |
| 2372 SetSourcePosition(prop->position()); | 2396 SetSourcePosition(prop->position()); |
| 2373 | 2397 |
| 2374 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); | 2398 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); |
| 2375 } | 2399 } |
| 2376 | 2400 |
| 2377 | 2401 |
| 2378 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2402 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2379 Token::Value op, | 2403 Token::Value op, |
| 2380 OverwriteMode mode, | |
| 2381 Expression* left_expr, | 2404 Expression* left_expr, |
| 2382 Expression* right_expr) { | 2405 Expression* right_expr) { |
| 2383 Label done, smi_case, stub_call; | 2406 Label done, smi_case, stub_call; |
| 2384 | 2407 |
| 2385 Register scratch1 = r5; | 2408 Register scratch1 = r5; |
| 2386 Register scratch2 = r6; | 2409 Register scratch2 = r6; |
| 2387 | 2410 |
| 2388 // Get the arguments. | 2411 // Get the arguments. |
| 2389 Register left = r4; | 2412 Register left = r4; |
| 2390 Register right = r3; | 2413 Register right = r3; |
| 2391 __ pop(left); | 2414 __ pop(left); |
| 2392 | 2415 |
| 2393 // Perform combined smi check on both operands. | 2416 // Perform combined smi check on both operands. |
| 2394 __ orx(scratch1, left, right); | 2417 __ orx(scratch1, left, right); |
| 2395 STATIC_ASSERT(kSmiTag == 0); | 2418 STATIC_ASSERT(kSmiTag == 0); |
| 2396 JumpPatchSite patch_site(masm_); | 2419 JumpPatchSite patch_site(masm_); |
| 2397 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2420 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2398 | 2421 |
| 2399 __ bind(&stub_call); | 2422 __ bind(&stub_call); |
| 2400 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); | 2423 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
| 2401 CallIC(code, expr->BinaryOperationFeedbackId()); | 2424 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2402 patch_site.EmitPatchInfo(); | 2425 patch_site.EmitPatchInfo(); |
| 2403 __ b(&done); | 2426 __ b(&done); |
| 2404 | 2427 |
| 2405 __ bind(&smi_case); | 2428 __ bind(&smi_case); |
| 2406 // Smi case. This code works the same way as the smi-smi case in the type | 2429 // Smi case. This code works the same way as the smi-smi case in the type |
| 2407 // recording binary operation stub. | 2430 // recording binary operation stub. |
| 2408 switch (op) { | 2431 switch (op) { |
| 2409 case Token::SAR: | 2432 case Token::SAR: |
| 2410 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2433 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2428 __ SmiUntag(scratch1, left); | 2451 __ SmiUntag(scratch1, left); |
| 2429 __ GetLeastBitsFromSmi(scratch2, right, 5); | 2452 __ GetLeastBitsFromSmi(scratch2, right, 5); |
| 2430 __ srw(scratch1, scratch1, scratch2); | 2453 __ srw(scratch1, scratch1, scratch2); |
| 2431 // Unsigned shift is not allowed to produce a negative number. | 2454 // Unsigned shift is not allowed to produce a negative number. |
| 2432 __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &stub_call); | 2455 __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &stub_call); |
| 2433 __ SmiTag(right, scratch1); | 2456 __ SmiTag(right, scratch1); |
| 2434 break; | 2457 break; |
| 2435 } | 2458 } |
| 2436 case Token::ADD: { | 2459 case Token::ADD: { |
| 2437 __ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0); | 2460 __ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
| 2438 __ bne(&stub_call, cr0); | 2461 __ BranchOnOverflow(&stub_call); |
| 2439 __ mr(right, scratch1); | 2462 __ mr(right, scratch1); |
| 2440 break; | 2463 break; |
| 2441 } | 2464 } |
| 2442 case Token::SUB: { | 2465 case Token::SUB: { |
| 2443 __ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0); | 2466 __ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
| 2444 __ bne(&stub_call, cr0); | 2467 __ BranchOnOverflow(&stub_call); |
| 2445 __ mr(right, scratch1); | 2468 __ mr(right, scratch1); |
| 2446 break; | 2469 break; |
| 2447 } | 2470 } |
| 2448 case Token::MUL: { | 2471 case Token::MUL: { |
| 2449 Label mul_zero; | 2472 Label mul_zero; |
| 2450 #if V8_TARGET_ARCH_PPC64 | 2473 #if V8_TARGET_ARCH_PPC64 |
| 2451 // Remove tag from both operands. | 2474 // Remove tag from both operands. |
| 2452 __ SmiUntag(ip, right); | 2475 __ SmiUntag(ip, right); |
| 2453 __ SmiUntag(r0, left); | 2476 __ SmiUntag(r0, left); |
| 2454 __ Mul(scratch1, r0, ip); | 2477 __ Mul(scratch1, r0, ip); |
| 2455 // Check for overflowing the smi range - no overflow if higher 33 bits of | 2478 // Check for overflowing the smi range - no overflow if higher 33 bits of |
| 2456 // the result are identical. | 2479 // the result are identical. |
| 2457 __ TestIfInt32(scratch1, scratch2, ip); | 2480 __ TestIfInt32(scratch1, r0); |
| 2458 __ bne(&stub_call); | 2481 __ bne(&stub_call); |
| 2459 #else | 2482 #else |
| 2460 __ SmiUntag(ip, right); | 2483 __ SmiUntag(ip, right); |
| 2461 __ mullw(scratch1, left, ip); | 2484 __ mullw(scratch1, left, ip); |
| 2462 __ mulhw(scratch2, left, ip); | 2485 __ mulhw(scratch2, left, ip); |
| 2463 // Check for overflowing the smi range - no overflow if higher 33 bits of | 2486 // Check for overflowing the smi range - no overflow if higher 33 bits of |
| 2464 // the result are identical. | 2487 // the result are identical. |
| 2465 __ TestIfInt32(scratch2, scratch1, ip); | 2488 __ TestIfInt32(scratch2, scratch1, ip); |
| 2466 __ bne(&stub_call); | 2489 __ bne(&stub_call); |
| 2467 #endif | 2490 #endif |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2508 | 2531 |
| 2509 // No access check is needed here since the constructor is created by the | 2532 // No access check is needed here since the constructor is created by the |
| 2510 // class literal. | 2533 // class literal. |
| 2511 Register scratch = r4; | 2534 Register scratch = r4; |
| 2512 __ LoadP(scratch, | 2535 __ LoadP(scratch, |
| 2513 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); | 2536 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2514 __ push(scratch); | 2537 __ push(scratch); |
| 2515 | 2538 |
| 2516 for (int i = 0; i < lit->properties()->length(); i++) { | 2539 for (int i = 0; i < lit->properties()->length(); i++) { |
| 2517 ObjectLiteral::Property* property = lit->properties()->at(i); | 2540 ObjectLiteral::Property* property = lit->properties()->at(i); |
| 2518 Literal* key = property->key()->AsLiteral(); | |
| 2519 Expression* value = property->value(); | 2541 Expression* value = property->value(); |
| 2520 DCHECK(key != NULL); | |
| 2521 | 2542 |
| 2522 if (property->is_static()) { | 2543 if (property->is_static()) { |
| 2523 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor | 2544 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor |
| 2524 } else { | 2545 } else { |
| 2525 __ LoadP(scratch, MemOperand(sp, 0)); // prototype | 2546 __ LoadP(scratch, MemOperand(sp, 0)); // prototype |
| 2526 } | 2547 } |
| 2527 __ push(scratch); | 2548 __ push(scratch); |
| 2528 VisitForStackValue(key); | 2549 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
| 2529 VisitForStackValue(value); | 2550 VisitForStackValue(value); |
| 2551 EmitSetHomeObjectIfNeeded(value, 2); |
| 2530 | 2552 |
| 2531 switch (property->kind()) { | 2553 switch (property->kind()) { |
| 2532 case ObjectLiteral::Property::CONSTANT: | 2554 case ObjectLiteral::Property::CONSTANT: |
| 2533 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2555 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2534 case ObjectLiteral::Property::PROTOTYPE: | 2556 case ObjectLiteral::Property::PROTOTYPE: |
| 2535 UNREACHABLE(); | 2557 UNREACHABLE(); |
| 2536 case ObjectLiteral::Property::COMPUTED: | 2558 case ObjectLiteral::Property::COMPUTED: |
| 2537 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2559 __ CallRuntime(Runtime::kDefineClassMethod, 3); |
| 2538 break; | 2560 break; |
| 2539 | 2561 |
| 2540 case ObjectLiteral::Property::GETTER: | 2562 case ObjectLiteral::Property::GETTER: |
| 2541 __ CallRuntime(Runtime::kDefineClassGetter, 3); | 2563 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2564 __ push(r3); |
| 2565 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
| 2542 break; | 2566 break; |
| 2543 | 2567 |
| 2544 case ObjectLiteral::Property::SETTER: | 2568 case ObjectLiteral::Property::SETTER: |
| 2545 __ CallRuntime(Runtime::kDefineClassSetter, 3); | 2569 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2570 __ push(r3); |
| 2571 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
| 2546 break; | 2572 break; |
| 2547 | 2573 |
| 2548 default: | 2574 default: |
| 2549 UNREACHABLE(); | 2575 UNREACHABLE(); |
| 2550 } | 2576 } |
| 2551 } | 2577 } |
| 2552 | 2578 |
| 2553 // prototype | 2579 // prototype |
| 2554 __ CallRuntime(Runtime::kToFastProperties, 1); | 2580 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2555 | 2581 |
| 2556 // constructor | 2582 // constructor |
| 2557 __ CallRuntime(Runtime::kToFastProperties, 1); | 2583 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2558 } | 2584 } |
| 2559 | 2585 |
| 2560 | 2586 |
| 2561 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op, | 2587 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
| 2562 OverwriteMode mode) { | |
| 2563 __ pop(r4); | 2588 __ pop(r4); |
| 2564 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); | 2589 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
| 2565 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2590 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2566 CallIC(code, expr->BinaryOperationFeedbackId()); | 2591 CallIC(code, expr->BinaryOperationFeedbackId()); |
| 2567 patch_site.EmitPatchInfo(); | 2592 patch_site.EmitPatchInfo(); |
| 2568 context()->Plug(r3); | 2593 context()->Plug(r3); |
| 2569 } | 2594 } |
| 2570 | 2595 |
| 2571 | 2596 |
| 2572 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2597 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2573 DCHECK(expr->IsValidReferenceExpression()); | 2598 DCHECK(expr->IsValidReferenceExpression()); |
| 2574 | 2599 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2629 break; | 2654 break; |
| 2630 } | 2655 } |
| 2631 case KEYED_PROPERTY: { | 2656 case KEYED_PROPERTY: { |
| 2632 __ push(r3); // Preserve value. | 2657 __ push(r3); // Preserve value. |
| 2633 VisitForStackValue(prop->obj()); | 2658 VisitForStackValue(prop->obj()); |
| 2634 VisitForAccumulatorValue(prop->key()); | 2659 VisitForAccumulatorValue(prop->key()); |
| 2635 __ Move(StoreDescriptor::NameRegister(), r3); | 2660 __ Move(StoreDescriptor::NameRegister(), r3); |
| 2636 __ Pop(StoreDescriptor::ValueRegister(), | 2661 __ Pop(StoreDescriptor::ValueRegister(), |
| 2637 StoreDescriptor::ReceiverRegister()); | 2662 StoreDescriptor::ReceiverRegister()); |
| 2638 Handle<Code> ic = | 2663 Handle<Code> ic = |
| 2639 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 2664 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 2640 CallIC(ic); | 2665 CallIC(ic); |
| 2641 break; | 2666 break; |
| 2642 } | 2667 } |
| 2643 } | 2668 } |
| 2644 context()->Plug(r3); | 2669 context()->Plug(r3); |
| 2645 } | 2670 } |
| 2646 | 2671 |
| 2647 | 2672 |
| 2648 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( | 2673 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2649 Variable* var, MemOperand location) { | 2674 Variable* var, MemOperand location) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2698 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2723 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2699 // Perform the assignment. | 2724 // Perform the assignment. |
| 2700 __ bind(&assign); | 2725 __ bind(&assign); |
| 2701 EmitStoreToStackLocalOrContextSlot(var, location); | 2726 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2702 | 2727 |
| 2703 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2728 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2704 if (var->IsLookupSlot()) { | 2729 if (var->IsLookupSlot()) { |
| 2705 // Assignment to var. | 2730 // Assignment to var. |
| 2706 __ push(r3); // Value. | 2731 __ push(r3); // Value. |
| 2707 __ mov(r4, Operand(var->name())); | 2732 __ mov(r4, Operand(var->name())); |
| 2708 __ mov(r3, Operand(Smi::FromInt(strict_mode()))); | 2733 __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
| 2709 __ Push(cp, r4, r3); // Context, name, strict mode. | 2734 __ Push(cp, r4, r3); // Context, name, language mode. |
| 2710 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2735 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
| 2711 } else { | 2736 } else { |
| 2712 // Assignment to var or initializing assignment to let/const in harmony | 2737 // Assignment to var or initializing assignment to let/const in harmony |
| 2713 // mode. | 2738 // mode. |
| 2714 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2739 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
| 2715 MemOperand location = VarOperand(var, r4); | 2740 MemOperand location = VarOperand(var, r4); |
| 2716 if (generate_debug_code_ && op == Token::INIT_LET) { | 2741 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2717 // Check for an uninitialized let binding. | 2742 // Check for an uninitialized let binding. |
| 2718 __ LoadP(r5, location); | 2743 __ LoadP(r5, location); |
| 2719 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2744 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2720 __ Check(eq, kLetBindingReInitialization); | 2745 __ Check(eq, kLetBindingReInitialization); |
| 2721 } | 2746 } |
| 2722 EmitStoreToStackLocalOrContextSlot(var, location); | 2747 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2723 } | 2748 } |
| 2749 } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { |
| 2750 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
| 2724 } | 2751 } |
| 2725 // Non-initializing assignments to consts are ignored. | |
| 2726 } | 2752 } |
| 2727 | 2753 |
| 2728 | 2754 |
| 2729 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2755 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2730 // Assignment to a property, using a named store IC. | 2756 // Assignment to a property, using a named store IC. |
| 2731 Property* prop = expr->target()->AsProperty(); | 2757 Property* prop = expr->target()->AsProperty(); |
| 2732 DCHECK(prop != NULL); | 2758 DCHECK(prop != NULL); |
| 2733 DCHECK(prop->key()->IsLiteral()); | 2759 DCHECK(prop->key()->IsLiteral()); |
| 2734 | 2760 |
| 2735 // Record source code position before IC call. | 2761 // Record source code position before IC call. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2747 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { | 2773 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
| 2748 // Assignment to named property of super. | 2774 // Assignment to named property of super. |
| 2749 // r3 : value | 2775 // r3 : value |
| 2750 // stack : receiver ('this'), home_object | 2776 // stack : receiver ('this'), home_object |
| 2751 DCHECK(prop != NULL); | 2777 DCHECK(prop != NULL); |
| 2752 Literal* key = prop->key()->AsLiteral(); | 2778 Literal* key = prop->key()->AsLiteral(); |
| 2753 DCHECK(key != NULL); | 2779 DCHECK(key != NULL); |
| 2754 | 2780 |
| 2755 __ Push(key->value()); | 2781 __ Push(key->value()); |
| 2756 __ Push(r3); | 2782 __ Push(r3); |
| 2757 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict | 2783 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
| 2758 : Runtime::kStoreToSuper_Sloppy), | 2784 : Runtime::kStoreToSuper_Sloppy), |
| 2759 4); | 2785 4); |
| 2760 } | 2786 } |
| 2761 | 2787 |
| 2762 | 2788 |
| 2763 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2789 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
| 2764 // Assignment to named property of super. | 2790 // Assignment to named property of super. |
| 2765 // r3 : value | 2791 // r3 : value |
| 2766 // stack : receiver ('this'), home_object, key | 2792 // stack : receiver ('this'), home_object, key |
| 2767 DCHECK(prop != NULL); | 2793 DCHECK(prop != NULL); |
| 2768 | 2794 |
| 2769 __ Push(r3); | 2795 __ Push(r3); |
| 2770 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict | 2796 __ CallRuntime( |
| 2771 : Runtime::kStoreKeyedToSuper_Sloppy), | 2797 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 2772 4); | 2798 : Runtime::kStoreKeyedToSuper_Sloppy), |
| 2799 4); |
| 2773 } | 2800 } |
| 2774 | 2801 |
| 2775 | 2802 |
| 2776 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2803 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2777 // Assignment to a property, using a keyed store IC. | 2804 // Assignment to a property, using a keyed store IC. |
| 2778 | 2805 |
| 2779 // Record source code position before IC call. | 2806 // Record source code position before IC call. |
| 2780 SetSourcePosition(expr->position()); | 2807 SetSourcePosition(expr->position()); |
| 2781 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); | 2808 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); |
| 2782 DCHECK(StoreDescriptor::ValueRegister().is(r3)); | 2809 DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
| 2783 | 2810 |
| 2784 Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 2811 Handle<Code> ic = |
| 2812 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 2785 CallIC(ic, expr->AssignmentFeedbackId()); | 2813 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2786 | 2814 |
| 2787 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2815 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2788 context()->Plug(r3); | 2816 context()->Plug(r3); |
| 2789 } | 2817 } |
| 2790 | 2818 |
| 2791 | 2819 |
| 2792 void FullCodeGenerator::VisitProperty(Property* expr) { | 2820 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2793 Comment cmnt(masm_, "[ Property"); | 2821 Comment cmnt(masm_, "[ Property"); |
| 2794 Expression* key = expr->key(); | 2822 Expression* key = expr->key(); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2966 int arg_count = args->length(); | 2994 int arg_count = args->length(); |
| 2967 { | 2995 { |
| 2968 PreservePositionScope scope(masm()->positions_recorder()); | 2996 PreservePositionScope scope(masm()->positions_recorder()); |
| 2969 for (int i = 0; i < arg_count; i++) { | 2997 for (int i = 0; i < arg_count; i++) { |
| 2970 VisitForStackValue(args->at(i)); | 2998 VisitForStackValue(args->at(i)); |
| 2971 } | 2999 } |
| 2972 } | 3000 } |
| 2973 | 3001 |
| 2974 // Record source position of the IC call. | 3002 // Record source position of the IC call. |
| 2975 SetSourcePosition(expr->position()); | 3003 SetSourcePosition(expr->position()); |
| 2976 Handle<Code> ic = CallIC::initialize_stub(isolate(), arg_count, call_type); | 3004 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); |
| 2977 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); | 3005 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackICSlot())); |
| 2978 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 3006 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
| 2979 // Don't assign a type feedback id to the IC, since type feedback is provided | 3007 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2980 // by the vector above. | 3008 // by the vector above. |
| 2981 CallIC(ic); | 3009 CallIC(ic); |
| 2982 | 3010 |
| 2983 RecordJSReturnSite(expr); | 3011 RecordJSReturnSite(expr); |
| 2984 // Restore context register. | 3012 // Restore context register. |
| 2985 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3013 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2986 context()->DropAndPlug(1, r3); | 3014 context()->DropAndPlug(1, r3); |
| 2987 } | 3015 } |
| 2988 | 3016 |
| 2989 | 3017 |
| 2990 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 3018 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2991 // r8: copy of the first argument or undefined if it doesn't exist. | 3019 // r8: copy of the first argument or undefined if it doesn't exist. |
| 2992 if (arg_count > 0) { | 3020 if (arg_count > 0) { |
| 2993 __ LoadP(r8, MemOperand(sp, arg_count * kPointerSize), r0); | 3021 __ LoadP(r8, MemOperand(sp, arg_count * kPointerSize), r0); |
| 2994 } else { | 3022 } else { |
| 2995 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 3023 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
| 2996 } | 3024 } |
| 2997 | 3025 |
| 2998 // r7: the receiver of the enclosing function. | 3026 // r7: the receiver of the enclosing function. |
| 2999 __ LoadP(r7, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3027 __ LoadP(r7, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3000 | 3028 |
| 3001 // r6: the receiver of the enclosing function. | 3029 // r6: the receiver of the enclosing function. |
| 3002 int receiver_offset = 2 + info_->scope()->num_parameters(); | 3030 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 3003 __ LoadP(r6, MemOperand(fp, receiver_offset * kPointerSize), r0); | 3031 __ LoadP(r6, MemOperand(fp, receiver_offset * kPointerSize), r0); |
| 3004 | 3032 |
| 3005 // r5: strict mode. | 3033 // r5: language mode. |
| 3006 __ LoadSmiLiteral(r5, Smi::FromInt(strict_mode())); | 3034 __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); |
| 3007 | 3035 |
| 3008 // r4: the start position of the scope the calls resides in. | 3036 // r4: the start position of the scope the calls resides in. |
| 3009 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); | 3037 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); |
| 3010 | 3038 |
| 3011 // Do the runtime call. | 3039 // Do the runtime call. |
| 3012 __ Push(r8, r7, r6, r5, r4); | 3040 __ Push(r8, r7, r6, r5, r4); |
| 3013 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); | 3041 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); |
| 3014 } | 3042 } |
| 3015 | 3043 |
| 3016 | 3044 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3133 PreservePositionScope scope(masm()->positions_recorder()); | 3161 PreservePositionScope scope(masm()->positions_recorder()); |
| 3134 VisitForStackValue(property->obj()); | 3162 VisitForStackValue(property->obj()); |
| 3135 } | 3163 } |
| 3136 if (is_named_call) { | 3164 if (is_named_call) { |
| 3137 EmitCallWithLoadIC(expr); | 3165 EmitCallWithLoadIC(expr); |
| 3138 } else { | 3166 } else { |
| 3139 EmitKeyedCallWithLoadIC(expr, property->key()); | 3167 EmitKeyedCallWithLoadIC(expr, property->key()); |
| 3140 } | 3168 } |
| 3141 } | 3169 } |
| 3142 } else if (call_type == Call::SUPER_CALL) { | 3170 } else if (call_type == Call::SUPER_CALL) { |
| 3143 SuperReference* super_ref = callee->AsSuperReference(); | 3171 if (FLAG_experimental_classes) { |
| 3144 EmitLoadSuperConstructor(super_ref); | 3172 EmitSuperConstructorCall(expr); |
| 3145 __ Push(result_register()); | 3173 } else { |
| 3146 VisitForStackValue(super_ref->this_var()); | 3174 SuperReference* super_ref = callee->AsSuperReference(); |
| 3147 EmitCall(expr, CallICState::METHOD); | 3175 EmitLoadSuperConstructor(super_ref); |
| 3176 __ Push(result_register()); |
| 3177 VisitForStackValue(super_ref->this_var()); |
| 3178 EmitCall(expr, CallICState::METHOD); |
| 3179 } |
| 3148 } else { | 3180 } else { |
| 3149 DCHECK(call_type == Call::OTHER_CALL); | 3181 DCHECK(call_type == Call::OTHER_CALL); |
| 3150 // Call to an arbitrary expression not handled specially above. | 3182 // Call to an arbitrary expression not handled specially above. |
| 3151 { | 3183 { |
| 3152 PreservePositionScope scope(masm()->positions_recorder()); | 3184 PreservePositionScope scope(masm()->positions_recorder()); |
| 3153 VisitForStackValue(callee); | 3185 VisitForStackValue(callee); |
| 3154 } | 3186 } |
| 3155 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 3187 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
| 3156 __ push(r4); | 3188 __ push(r4); |
| 3157 // Emit function call. | 3189 // Emit function call. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3206 __ Move(r5, FeedbackVector()); | 3238 __ Move(r5, FeedbackVector()); |
| 3207 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallNewFeedbackSlot())); | 3239 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallNewFeedbackSlot())); |
| 3208 | 3240 |
| 3209 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 3241 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
| 3210 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 3242 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 3211 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 3243 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 3212 context()->Plug(r3); | 3244 context()->Plug(r3); |
| 3213 } | 3245 } |
| 3214 | 3246 |
| 3215 | 3247 |
| 3248 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
| 3249 SuperReference* super_ref = expr->expression()->AsSuperReference(); |
| 3250 EmitLoadSuperConstructor(super_ref); |
| 3251 __ push(result_register()); |
| 3252 |
| 3253 Variable* this_var = super_ref->this_var()->var(); |
| 3254 |
| 3255 GetVar(r3, this_var); |
| 3256 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 3257 Label uninitialized_this; |
| 3258 __ beq(&uninitialized_this); |
| 3259 __ mov(r3, Operand(this_var->name())); |
| 3260 __ push(r3); |
| 3261 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 3262 __ bind(&uninitialized_this); |
| 3263 |
| 3264 // Push the arguments ("left-to-right") on the stack. |
| 3265 ZoneList<Expression*>* args = expr->arguments(); |
| 3266 int arg_count = args->length(); |
| 3267 for (int i = 0; i < arg_count; i++) { |
| 3268 VisitForStackValue(args->at(i)); |
| 3269 } |
| 3270 |
| 3271 // Call the construct call builtin that handles allocation and |
| 3272 // constructor invocation. |
| 3273 SetSourcePosition(expr->position()); |
| 3274 |
| 3275 // Load function and argument count into r1 and r0. |
| 3276 __ mov(r3, Operand(arg_count)); |
| 3277 __ LoadP(r4, MemOperand(sp, arg_count * kPointerSize)); |
| 3278 |
| 3279 // Record call targets in unoptimized code. |
| 3280 if (FLAG_pretenuring_call_new) { |
| 3281 UNREACHABLE(); |
| 3282 /* TODO(dslomov): support pretenuring. |
| 3283 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
| 3284 DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == |
| 3285 expr->CallNewFeedbackSlot().ToInt() + 1); |
| 3286 */ |
| 3287 } |
| 3288 |
| 3289 __ Move(r5, FeedbackVector()); |
| 3290 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); |
| 3291 |
| 3292 // TODO(dslomov): use a different stub and propagate new.target. |
| 3293 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
| 3294 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 3295 |
| 3296 RecordJSReturnSite(expr); |
| 3297 |
| 3298 EmitVariableAssignment(this_var, Token::INIT_CONST); |
| 3299 context()->Plug(r3); |
| 3300 } |
| 3301 |
| 3302 |
| 3216 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 3303 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
| 3217 ZoneList<Expression*>* args = expr->arguments(); | 3304 ZoneList<Expression*>* args = expr->arguments(); |
| 3218 DCHECK(args->length() == 1); | 3305 DCHECK(args->length() == 1); |
| 3219 | 3306 |
| 3220 VisitForAccumulatorValue(args->at(0)); | 3307 VisitForAccumulatorValue(args->at(0)); |
| 3221 | 3308 |
| 3222 Label materialize_true, materialize_false; | 3309 Label materialize_true, materialize_false; |
| 3223 Label* if_true = NULL; | 3310 Label* if_true = NULL; |
| 3224 Label* if_false = NULL; | 3311 Label* if_false = NULL; |
| 3225 Label* fall_through = NULL; | 3312 Label* fall_through = NULL; |
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4505 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4592 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4506 switch (expr->op()) { | 4593 switch (expr->op()) { |
| 4507 case Token::DELETE: { | 4594 case Token::DELETE: { |
| 4508 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4595 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4509 Property* property = expr->expression()->AsProperty(); | 4596 Property* property = expr->expression()->AsProperty(); |
| 4510 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4597 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4511 | 4598 |
| 4512 if (property != NULL) { | 4599 if (property != NULL) { |
| 4513 VisitForStackValue(property->obj()); | 4600 VisitForStackValue(property->obj()); |
| 4514 VisitForStackValue(property->key()); | 4601 VisitForStackValue(property->key()); |
| 4515 __ LoadSmiLiteral(r4, Smi::FromInt(strict_mode())); | 4602 __ LoadSmiLiteral(r4, Smi::FromInt(language_mode())); |
| 4516 __ push(r4); | 4603 __ push(r4); |
| 4517 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4604 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4518 context()->Plug(r3); | 4605 context()->Plug(r3); |
| 4519 } else if (proxy != NULL) { | 4606 } else if (proxy != NULL) { |
| 4520 Variable* var = proxy->var(); | 4607 Variable* var = proxy->var(); |
| 4521 // Delete of an unqualified identifier is disallowed in strict mode | 4608 // Delete of an unqualified identifier is disallowed in strict mode |
| 4522 // but "delete this" is allowed. | 4609 // but "delete this" is allowed. |
| 4523 DCHECK(strict_mode() == SLOPPY || var->is_this()); | 4610 DCHECK(is_sloppy(language_mode()) || var->is_this()); |
| 4524 if (var->IsUnallocated()) { | 4611 if (var->IsUnallocated()) { |
| 4525 __ LoadP(r5, GlobalObjectOperand()); | 4612 __ LoadP(r5, GlobalObjectOperand()); |
| 4526 __ mov(r4, Operand(var->name())); | 4613 __ mov(r4, Operand(var->name())); |
| 4527 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); | 4614 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); |
| 4528 __ Push(r5, r4, r3); | 4615 __ Push(r5, r4, r3); |
| 4529 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4616 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4530 context()->Plug(r3); | 4617 context()->Plug(r3); |
| 4531 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4618 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4532 // Result of deleting non-global, non-dynamic variables is false. | 4619 // Result of deleting non-global, non-dynamic variables is false. |
| 4533 // The subexpression does not have side effects. | 4620 // The subexpression does not have side effects. |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4761 } | 4848 } |
| 4762 } | 4849 } |
| 4763 | 4850 |
| 4764 __ bind(&stub_call); | 4851 __ bind(&stub_call); |
| 4765 __ mr(r4, r3); | 4852 __ mr(r4, r3); |
| 4766 __ LoadSmiLiteral(r3, Smi::FromInt(count_value)); | 4853 __ LoadSmiLiteral(r3, Smi::FromInt(count_value)); |
| 4767 | 4854 |
| 4768 // Record position before stub call. | 4855 // Record position before stub call. |
| 4769 SetSourcePosition(expr->position()); | 4856 SetSourcePosition(expr->position()); |
| 4770 | 4857 |
| 4771 Handle<Code> code = | 4858 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); |
| 4772 CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); | |
| 4773 CallIC(code, expr->CountBinOpFeedbackId()); | 4859 CallIC(code, expr->CountBinOpFeedbackId()); |
| 4774 patch_site.EmitPatchInfo(); | 4860 patch_site.EmitPatchInfo(); |
| 4775 __ bind(&done); | 4861 __ bind(&done); |
| 4776 | 4862 |
| 4777 // Store the value returned in r3. | 4863 // Store the value returned in r3. |
| 4778 switch (assign_type) { | 4864 switch (assign_type) { |
| 4779 case VARIABLE: | 4865 case VARIABLE: |
| 4780 if (expr->is_postfix()) { | 4866 if (expr->is_postfix()) { |
| 4781 { | 4867 { |
| 4782 EffectContext context(this); | 4868 EffectContext context(this); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4831 } | 4917 } |
| 4832 } else { | 4918 } else { |
| 4833 context()->Plug(r3); | 4919 context()->Plug(r3); |
| 4834 } | 4920 } |
| 4835 break; | 4921 break; |
| 4836 } | 4922 } |
| 4837 case KEYED_PROPERTY: { | 4923 case KEYED_PROPERTY: { |
| 4838 __ Pop(StoreDescriptor::ReceiverRegister(), | 4924 __ Pop(StoreDescriptor::ReceiverRegister(), |
| 4839 StoreDescriptor::NameRegister()); | 4925 StoreDescriptor::NameRegister()); |
| 4840 Handle<Code> ic = | 4926 Handle<Code> ic = |
| 4841 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 4927 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
| 4842 CallIC(ic, expr->CountStoreFeedbackId()); | 4928 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4843 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4929 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4844 if (expr->is_postfix()) { | 4930 if (expr->is_postfix()) { |
| 4845 if (!context()->IsEffect()) { | 4931 if (!context()->IsEffect()) { |
| 4846 context()->PlugTOS(); | 4932 context()->PlugTOS(); |
| 4847 } | 4933 } |
| 4848 } else { | 4934 } else { |
| 4849 context()->Plug(r3); | 4935 context()->Plug(r3); |
| 4850 } | 4936 } |
| 4851 break; | 4937 break; |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5285 return ON_STACK_REPLACEMENT; | 5371 return ON_STACK_REPLACEMENT; |
| 5286 } | 5372 } |
| 5287 | 5373 |
| 5288 DCHECK(interrupt_address == | 5374 DCHECK(interrupt_address == |
| 5289 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5375 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 5290 return OSR_AFTER_STACK_CHECK; | 5376 return OSR_AFTER_STACK_CHECK; |
| 5291 } | 5377 } |
| 5292 } | 5378 } |
| 5293 } // namespace v8::internal | 5379 } // namespace v8::internal |
| 5294 #endif // V8_TARGET_ARCH_PPC | 5380 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |