Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <sstream> | 10 #include <sstream> |
| (...skipping 6536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6547 PropertyDescriptor* desc, | 6547 PropertyDescriptor* desc, |
| 6548 ShouldThrow should_throw) { | 6548 ShouldThrow should_throw) { |
| 6549 if (object->IsJSArray()) { | 6549 if (object->IsJSArray()) { |
| 6550 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), | 6550 return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object), |
| 6551 key, desc, should_throw); | 6551 key, desc, should_throw); |
| 6552 } | 6552 } |
| 6553 if (object->IsJSProxy()) { | 6553 if (object->IsJSProxy()) { |
| 6554 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), | 6554 return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object), |
| 6555 key, desc, should_throw); | 6555 key, desc, should_throw); |
| 6556 } | 6556 } |
| 6557 // TODO(jkummerow): Support Modules (ES6 9.4.6.6) | 6557 // TODO(neis): Special case for JSModuleNamespace? |
| 6558 | 6558 |
| 6559 // OrdinaryDefineOwnProperty, by virtue of calling | 6559 // OrdinaryDefineOwnProperty, by virtue of calling |
| 6560 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) | 6560 // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2) |
| 6561 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: | 6561 // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception: |
| 6562 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. | 6562 // TODO(jkummerow): Setting an indexed accessor on a typed array should throw. |
| 6563 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, | 6563 return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key, |
| 6564 desc, should_throw); | 6564 desc, should_throw); |
| 6565 } | 6565 } |
| 6566 | 6566 |
| 6567 | 6567 |
| (...skipping 11662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 18230 DCHECK(IsKey(isolate, *key)); | 18230 DCHECK(IsKey(isolate, *key)); |
| 18231 | 18231 |
| 18232 // If the object does not have an identity hash, it was never used as a key. | 18232 // If the object does not have an identity hash, it was never used as a key. |
| 18233 Object* hash = key->GetHash(); | 18233 Object* hash = key->GetHash(); |
| 18234 if (hash->IsUndefined(isolate)) { | 18234 if (hash->IsUndefined(isolate)) { |
| 18235 return isolate->heap()->the_hole_value(); | 18235 return isolate->heap()->the_hole_value(); |
| 18236 } | 18236 } |
| 18237 return Lookup(isolate, key, Smi::cast(hash)->value()); | 18237 return Lookup(isolate, key, Smi::cast(hash)->value()); |
| 18238 } | 18238 } |
| 18239 | 18239 |
| 18240 Object* ObjectHashTable::ValueAt(int entry) { | |
| 18241 return get(EntryToValueIndex(entry)); | |
| 18242 } | |
| 18240 | 18243 |
| 18241 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { | 18244 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) { |
| 18242 return Lookup(GetIsolate(), key, hash); | 18245 return Lookup(GetIsolate(), key, hash); |
| 18243 } | 18246 } |
| 18244 | 18247 |
| 18245 | 18248 |
| 18246 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, | 18249 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table, |
| 18247 Handle<Object> key, | 18250 Handle<Object> key, |
| 18248 Handle<Object> value) { | 18251 Handle<Object> value) { |
| 18249 Isolate* isolate = table->GetIsolate(); | 18252 Isolate* isolate = table->GetIsolate(); |
| (...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19577 | 19580 |
| 19578 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) { | 19581 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) { |
| 19579 for (PrototypeIterator iter(isolate, this, kStartAtReceiver, | 19582 for (PrototypeIterator iter(isolate, this, kStartAtReceiver, |
| 19580 PrototypeIterator::END_AT_NULL); | 19583 PrototypeIterator::END_AT_NULL); |
| 19581 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { | 19584 !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) { |
| 19582 if (iter.GetCurrent<Object>()->IsJSProxy()) return true; | 19585 if (iter.GetCurrent<Object>()->IsJSProxy()) return true; |
| 19583 } | 19586 } |
| 19584 return false; | 19587 return false; |
| 19585 } | 19588 } |
| 19586 | 19589 |
| 19590 Object* JSModuleNamespace::Get(Handle<String> name) { | |
| 19591 Isolate* isolate = name->GetIsolate(); | |
| 19592 Handle<Object> object(module()->exports()->Lookup(name), isolate); | |
| 19593 return object->IsTheHole(isolate) ? isolate->heap()->undefined_value() | |
| 19594 : Handle<Cell>::cast(object)->value(); | |
| 19595 } | |
| 19596 | |
| 19587 namespace { | 19597 namespace { |
| 19588 | 19598 |
| 19589 template <typename T> | 19599 template <typename T> |
| 19590 struct HandleValueHash { | 19600 struct HandleValueHash { |
| 19591 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); } | 19601 V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); } |
| 19592 }; | 19602 }; |
| 19593 | 19603 |
| 19594 struct ModuleHandleEqual { | 19604 struct ModuleHandleEqual { |
| 19595 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const { | 19605 V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const { |
| 19596 return *lhs == *rhs; | 19606 return *lhs == *rhs; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 19608 StringHandleEqual, | 19618 StringHandleEqual, |
| 19609 zone_allocator<Handle<String>>> { | 19619 zone_allocator<Handle<String>>> { |
| 19610 public: | 19620 public: |
| 19611 explicit UnorderedStringSet(Zone* zone) | 19621 explicit UnorderedStringSet(Zone* zone) |
| 19612 : std::unordered_set<Handle<String>, HandleValueHash<String>, | 19622 : std::unordered_set<Handle<String>, HandleValueHash<String>, |
| 19613 StringHandleEqual, zone_allocator<Handle<String>>>( | 19623 StringHandleEqual, zone_allocator<Handle<String>>>( |
| 19614 2 /* bucket count */, HandleValueHash<String>(), | 19624 2 /* bucket count */, HandleValueHash<String>(), |
| 19615 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {} | 19625 StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {} |
| 19616 }; | 19626 }; |
| 19617 | 19627 |
| 19628 class UnorderedModuleSet | |
| 19629 : public std::unordered_set<Handle<Module>, HandleValueHash<Module>, | |
| 19630 ModuleHandleEqual, | |
| 19631 zone_allocator<Handle<Module>>> { | |
| 19632 public: | |
| 19633 explicit UnorderedModuleSet(Zone* zone) | |
| 19634 : std::unordered_set<Handle<Module>, HandleValueHash<Module>, | |
| 19635 ModuleHandleEqual, zone_allocator<Handle<Module>>>( | |
| 19636 2 /* bucket count */, HandleValueHash<Module>(), | |
| 19637 ModuleHandleEqual(), zone_allocator<Handle<Module>>(zone)) {} | |
| 19638 }; | |
| 19639 | |
| 19640 class UnorderedStringMap | |
| 19641 : public std::unordered_map< | |
| 19642 Handle<String>, Handle<Object>, HandleValueHash<String>, | |
| 19643 StringHandleEqual, | |
| 19644 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> { | |
| 19645 public: | |
| 19646 explicit UnorderedStringMap(Zone* zone) | |
| 19647 : std::unordered_map< | |
| 19648 Handle<String>, Handle<Object>, HandleValueHash<String>, | |
| 19649 StringHandleEqual, | |
| 19650 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>( | |
| 19651 2 /* bucket count */, HandleValueHash<String>(), | |
| 19652 StringHandleEqual(), | |
| 19653 zone_allocator<std::pair<const Handle<String>, Handle<Object>>>( | |
| 19654 zone)) {} | |
| 19655 }; | |
| 19656 | |
| 19618 } // anonymous namespace | 19657 } // anonymous namespace |
| 19619 | 19658 |
| 19620 class Module::ResolveSet | 19659 class Module::ResolveSet |
| 19621 : public std::unordered_map< | 19660 : public std::unordered_map< |
| 19622 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>, | 19661 Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>, |
| 19623 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>, | 19662 ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>, |
| 19624 UnorderedStringSet*>>> { | 19663 UnorderedStringSet*>>> { |
| 19625 public: | 19664 public: |
| 19626 explicit ResolveSet(Zone* zone) | 19665 explicit ResolveSet(Zone* zone) |
| 19627 : std::unordered_map<Handle<Module>, UnorderedStringSet*, | 19666 : std::unordered_map<Handle<Module>, UnorderedStringSet*, |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19931 Handle<Module> import(Module::cast(requested_modules->get(i)), isolate); | 19970 Handle<Module> import(Module::cast(requested_modules->get(i)), isolate); |
| 19932 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object); | 19971 RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object); |
| 19933 } | 19972 } |
| 19934 | 19973 |
| 19935 // Evaluation of module body. | 19974 // Evaluation of module body. |
| 19936 Handle<JSFunction> resume( | 19975 Handle<JSFunction> resume( |
| 19937 isolate->native_context()->generator_next_internal(), isolate); | 19976 isolate->native_context()->generator_next_internal(), isolate); |
| 19938 return Execution::Call(isolate, resume, generator, 0, nullptr); | 19977 return Execution::Call(isolate, resume, generator, 0, nullptr); |
| 19939 } | 19978 } |
| 19940 | 19979 |
| 19980 namespace { | |
|
adamk
2016/10/04 18:26:53
Please add a blank line after this (and before the
neis
2016/10/05 08:18:41
Done.
| |
| 19981 void FetchStarExports(Handle<Module> module, Zone* zone, | |
| 19982 UnorderedModuleSet* visited) { | |
| 19983 DCHECK(module->code()->IsJSFunction()); // Instantiated. | |
| 19984 | |
| 19985 bool cycle = !visited->insert(module).second; | |
| 19986 if (cycle) return; | |
| 19987 | |
| 19988 Isolate* isolate = module->GetIsolate(); | |
| 19989 Handle<ObjectHashTable> exports(module->exports(), isolate); | |
| 19990 UnorderedStringMap more_exports(zone); | |
| 19991 | |
| 19992 // TODO(neis): Only allocate more_exports if there are star exports. | |
| 19993 // Maybe split special_exports into indirect_exports and star_exports. | |
| 19994 | |
| 19995 Handle<FixedArray> special_exports(module->info()->special_exports(), | |
| 19996 isolate); | |
| 19997 for (int i = 0, n = special_exports->length(); i < n; ++i) { | |
| 19998 i::Handle<i::ModuleInfoEntry> entry( | |
|
adamk
2016/10/04 18:26:53
No need for i:: prefixes here (and below).
neis
2016/10/05 08:18:41
Done.
| |
| 19999 i::ModuleInfoEntry::cast(special_exports->get(i)), isolate); | |
| 20000 if (!entry->export_name()->IsUndefined(isolate)) { | |
| 20001 continue; // Indirect export. | |
| 20002 } | |
| 20003 | |
| 20004 int module_request = Smi::cast(entry->module_request())->value(); | |
| 20005 Handle<Module> requested_module( | |
| 20006 Module::cast(module->requested_modules()->get(module_request)), | |
| 20007 isolate); | |
| 20008 | |
| 20009 // Recurse. | |
| 20010 FetchStarExports(requested_module, zone, visited); | |
| 20011 | |
| 20012 // Collect all of [requested_module]'s exports that must be added to | |
| 20013 // [module]'s exports (i.e. to [exports]). We record these in | |
| 20014 // [more_exports]. Ambiguities (conflicting exports) are marked by mapping | |
| 20015 // the name to undefined instead of a Cell. | |
| 20016 Handle<ObjectHashTable> requested_exports(requested_module->exports(), | |
| 20017 isolate); | |
| 20018 for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) { | |
| 20019 Handle<Object> key(requested_exports->KeyAt(i), isolate); | |
| 20020 if (!requested_exports->IsKey(isolate, *key)) continue; | |
| 20021 if (Handle<String>::cast(key)->Equals(isolate->heap()->default_string())) | |
| 20022 continue; | |
| 20023 if (!exports->Lookup(key)->IsTheHole(isolate)) continue; | |
| 20024 | |
| 20025 Handle<String> name = Handle<String>::cast(key); | |
| 20026 Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate); | |
| 20027 auto it = more_exports.find(name); | |
| 20028 if (it == more_exports.end()) { | |
| 20029 more_exports.insert(std::make_pair(name, cell)); | |
|
adamk
2016/10/04 18:26:53
Please change this code to only do a single lookup
neis
2016/10/05 08:18:41
Done.
| |
| 20030 } else if (*it->second == *cell || it->second->IsUndefined(isolate)) { | |
| 20031 // We already recorded this mapping, or the name is ambiguous. In | |
| 20032 // either case, there's nothing to do. | |
| 20033 } else { | |
| 20034 DCHECK(it->second->IsCell()); | |
| 20035 // Different star exports provide different cells for this name, hence | |
| 20036 // mark the name as ambiguous. | |
| 20037 it->second = isolate->factory()->undefined_value(); | |
| 20038 } | |
| 20039 } | |
| 20040 } | |
| 20041 | |
| 20042 // Copy [more_exports] into [exports]. | |
| 20043 for (const auto& elem : more_exports) { | |
| 20044 if (elem.second->IsUndefined(isolate)) continue; // Ambiguous export. | |
| 20045 DCHECK(!elem.first->Equals(isolate->heap()->default_string())); | |
| 20046 DCHECK(elem.second->IsCell()); | |
| 20047 exports = ObjectHashTable::Put(exports, elem.first, elem.second); | |
| 20048 } | |
| 20049 module->set_exports(*exports); | |
| 20050 } | |
| 20051 } // anonymous namespace | |
| 20052 | |
| 20053 void Module::FetchStarExports(Handle<Module> module, Zone* zone) { | |
|
adamk
2016/10/04 18:26:53
Is this called anywhere other than below? Maybe ju
neis
2016/10/05 08:18:41
Ok, inlined it.
| |
| 20054 UnorderedModuleSet visited(zone); | |
| 20055 return i::FetchStarExports(module, zone, &visited); | |
| 20056 } | |
| 20057 | |
| 20058 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module, | |
| 20059 int module_request) { | |
| 20060 Isolate* isolate = module->GetIsolate(); | |
| 20061 Handle<Module> requested_module( | |
| 20062 Module::cast(module->requested_modules()->get(module_request)), isolate); | |
| 20063 return Module::GetModuleNamespace(requested_module); | |
| 20064 } | |
| 20065 | |
| 20066 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) { | |
| 20067 Isolate* isolate = module->GetIsolate(); | |
| 20068 | |
| 20069 Handle<HeapObject> object(module->module_namespace(), isolate); | |
| 20070 if (!object->IsUndefined(isolate)) { | |
| 20071 // Namespace object already exists. | |
| 20072 return Handle<JSModuleNamespace>::cast(object); | |
| 20073 } | |
| 20074 | |
| 20075 // Create the namespace object (initially empty). | |
| 20076 Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace(); | |
| 20077 ns->set_module(*module); | |
| 20078 module->set_module_namespace(*ns); | |
| 20079 | |
| 20080 // Collect the export names. | |
| 20081 Zone zone(isolate->allocator()); | |
| 20082 FetchStarExports(module, &zone); | |
| 20083 Handle<ObjectHashTable> exports(module->exports(), isolate); | |
| 20084 ZoneVector<Handle<String>> names(&zone); | |
| 20085 names.reserve(exports->NumberOfElements()); | |
| 20086 for (int i = 0, n = exports->Capacity(); i < n; ++i) { | |
| 20087 Handle<Object> key(exports->KeyAt(i), isolate); | |
| 20088 if (!exports->IsKey(isolate, *key)) continue; | |
| 20089 DCHECK(exports->ValueAt(i)->IsCell()); | |
| 20090 names.push_back(Handle<String>::cast(key)); | |
| 20091 } | |
| 20092 DCHECK_EQ(names.size(), exports->NumberOfElements()); | |
| 20093 | |
| 20094 // Sort them alphabetically. | |
| 20095 struct { | |
| 20096 bool operator()(Handle<String> a, Handle<String> b) { | |
| 20097 return String::Compare(a, b) == ComparisonResult::kLessThan; | |
| 20098 } | |
| 20099 } StringLess; | |
| 20100 std::sort(names.begin(), names.end(), StringLess); | |
| 20101 | |
| 20102 // Create the corresponding properties in the namespace object. | |
| 20103 PropertyAttributes attr = DONT_DELETE; | |
| 20104 for (const auto& name : names) { | |
| 20105 JSObject::SetAccessor( | |
| 20106 ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr)) | |
| 20107 .Check(); | |
| 20108 } | |
| 20109 JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked(); | |
| 20110 | |
| 20111 return ns; | |
| 20112 } | |
| 20113 | |
| 19941 } // namespace internal | 20114 } // namespace internal |
| 19942 } // namespace v8 | 20115 } // namespace v8 |
| OLD | NEW |