Index: src/code-stubs.cc |
diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
index c8693d2f8bc2eb8998a6a7d8a06da96a78ce4f54..53027574d40ee1cee8b2e509987bf16b6e8398ea 100644 |
--- a/src/code-stubs.cc |
+++ b/src/code-stubs.cc |
@@ -4471,6 +4471,101 @@ void StoreFieldStub::GenerateAssembly(CodeStubAssembler* assembler) const { |
} |
} |
+void StoreGlobalStub::GenerateAssembly(CodeStubAssembler* assembler) const { |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ |
+ assembler->Comment( |
+ "StoreGlobalStub: cell_type=%d, constant_type=%d, check_global=%d", |
+ cell_type(), PropertyCellType::kConstantType == cell_type() |
+ ? static_cast<int>(constant_type()) |
+ : -1, |
+ check_global()); |
+ |
+ Node* receiver = assembler->Parameter(Descriptor::kReceiver); |
+ Node* name = assembler->Parameter(Descriptor::kName); |
+ Node* value = assembler->Parameter(Descriptor::kValue); |
+ Node* slot = assembler->Parameter(Descriptor::kSlot); |
+ Node* vector = assembler->Parameter(Descriptor::kVector); |
+ Node* context = assembler->Parameter(Descriptor::kContext); |
+ |
+ Label miss(assembler); |
+ |
+ if (check_global()) { |
+ // Check that the map of the global has not changed: use a placeholder map |
+ // that will be replaced later with the global object's map. |
+ Node* proxy_map = assembler->LoadMap(receiver); |
+ Node* global = assembler->LoadObjectField(proxy_map, Map::kPrototypeOffset); |
+ Node* map_cell = assembler->HeapConstant(isolate()->factory()->NewWeakCell( |
+ StoreGlobalStub::global_map_placeholder(isolate()))); |
+ Node* expected_map = assembler->LoadWeakCellValue(map_cell); |
+ Node* map = assembler->LoadMap(global); |
+ assembler->GotoIf(assembler->WordNotEqual(expected_map, map), &miss); |
+ } |
+ |
+ Node* weak_cell = assembler->HeapConstant(isolate()->factory()->NewWeakCell( |
+ StoreGlobalStub::property_cell_placeholder(isolate()))); |
+ Node* cell = assembler->LoadWeakCellValue(weak_cell); |
+ assembler->GotoIf(assembler->WordIsSmi(cell), &miss); |
+ |
+ // Load the payload of the global parameter cell. A hole indicates that the |
+ // cell has been invalidated and that the store must be handled by the |
+ // runtime. |
+ Node* cell_contents = |
+ assembler->LoadObjectField(cell, PropertyCell::kValueOffset); |
+ |
+ PropertyCellType cell_type = this->cell_type(); |
+ if (cell_type == PropertyCellType::kConstant || |
+ cell_type == PropertyCellType::kUndefined) { |
+ // This is always valid for all states a cell can be in. |
+ assembler->GotoIf(assembler->WordNotEqual(cell_contents, value), &miss); |
+ } else { |
+ assembler->GotoIf( |
+ assembler->WordEqual(cell_contents, assembler->TheHoleConstant()), |
+ &miss); |
+ |
+ // When dealing with constant types, the type may be allowed to change, as |
+ // long as optimized code remains valid. |
+ bool value_is_smi = false; |
+ if (cell_type == PropertyCellType::kConstantType) { |
+ switch (constant_type()) { |
+ case PropertyCellConstantType::kSmi: |
+ assembler->GotoUnless(assembler->WordIsSmi(value), &miss); |
+ value_is_smi = true; |
+ break; |
+ case PropertyCellConstantType::kStableMap: { |
+ // It is sufficient here to check that the value and cell contents |
+ // have identical maps, no matter if they are stable or not or if they |
+ // are the maps that were originally in the cell or not. If optimized |
+ // code will deopt when a cell has a unstable map and if it has a |
+ // dependency on a stable map, it will deopt if the map destabilizes. |
+ assembler->GotoIf(assembler->WordIsSmi(value), &miss); |
+ assembler->GotoIf(assembler->WordIsSmi(cell_contents), &miss); |
+ Node* expected_map = assembler->LoadMap(cell_contents); |
+ Node* map = assembler->LoadMap(value); |
+ assembler->GotoIf(assembler->WordNotEqual(expected_map, map), &miss); |
+ break; |
+ } |
+ } |
+ } |
+ if (value_is_smi) { |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ cell, PropertyCell::kValueOffset, value); |
+ } else { |
+ assembler->StoreObjectField(cell, PropertyCell::kValueOffset, value); |
+ } |
+ } |
+ |
+ assembler->Return(value); |
+ |
+ assembler->Bind(&miss); |
+ { |
+ assembler->Comment("Miss"); |
+ assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, receiver, name, |
+ value, slot, vector); |
+ } |
+} |
+ |
// static |
compiler::Node* LessThanStub::Generate(CodeStubAssembler* assembler, |
compiler::Node* lhs, compiler::Node* rhs, |