예제 #1
0
LLVM_ATTRIBUTE_ALWAYS_INLINE
static const Metadata *findHashableBaseTypeImpl(const Metadata *type) {
  // Check the cache first.
  if (HashableConformanceEntry *entry =
          HashableConformances->find(HashableConformanceKey{type})) {
    return entry->baseTypeThatConformsToHashable;
  }
  if (!KnownToConformToHashable &&
      !swift_conformsToProtocol(type, &_TMps8Hashable)) {
    // Don't cache the negative response because we don't invalidate
    // this cache when a new conformance is loaded dynamically.
    return nullptr;
  }
  // By this point, `type` is known to conform to `Hashable`.

  const Metadata *baseTypeThatConformsToHashable = type;
  while (true) {
    const Metadata *superclass =
        _swift_class_getSuperclass(baseTypeThatConformsToHashable);
    if (!superclass)
      break;
    if (!swift_conformsToProtocol(superclass, &_TMps8Hashable))
      break;
    baseTypeThatConformsToHashable = superclass;
  }
  HashableConformances->getOrInsert(HashableConformanceKey{type},
                                    baseTypeThatConformsToHashable);
  return baseTypeThatConformsToHashable;
}
예제 #2
0
	void Render(double time)
	{
		static const Mat4f reflection(
			Vec4f( 1.0, 0.0, 0.0, 0.0),
			Vec4f( 0.0,-1.0, 0.0, 0.0),
			Vec4f( 0.0, 0.0, 1.0, 0.0),
			Vec4f( 0.0, 0.0, 0.0, 1.0)
		);

		auto camera = CamMatrixf::Orbiting(
			Vec3f(),
			GLfloat(7.0 + SineWave(time / 12.0)*2.5),
			FullCircles(time / 10.0),
			Degrees(45.0 - SineWave(time / 7.0)*35.0)
		);

		shape_prog.Use();
		shape.Bind();

		gl.Enable(Capability::CullFace);
		gl.FrontFace(make_shape.FaceWinding());

		// render into the off-screen framebuffer
		fbo.Bind(Framebuffer::Target::Draw);
		gl.Viewport(
			(width - refl_tex_side) / 2,
			(height - refl_tex_side) / 2,
			refl_tex_side, refl_tex_side
		);
		gl.Clear().ColorBuffer().DepthBuffer();

		shape_camera_matrix.Set(
			camera *
			ModelMatrixf::Translation(0.0f, -1.0f, 0.0f) *
			reflection
		);

		gl.CullFace(Face::Front);
		shape_instr.Draw(shape_indices);

		gl.Bind(Framebuffer::Target::Draw, DefaultFramebuffer());
		gl.Viewport(width, height);
		gl.Clear().ColorBuffer().DepthBuffer();

		shape_camera_matrix.Set(camera);

		gl.CullFace(Face::Back);
		shape_instr.Draw(shape_indices);

		gl.Disable(Capability::CullFace);

		// Render the plane
		plane_prog.Use();
		plane.Bind();

		plane_camera_matrix.Set(camera);
		plane_camera_position.Set(camera.Position());

		plane_instr.Draw(plane_indices);
	}
예제 #3
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();
		//
		// set the matrix for camera orbiting the origin
		camera_matrix.Set(
			CamMatrixf::Orbiting(
				Vec3f(),
				4.5,
				Degrees(time * 35),
				Degrees(SineWave(time / 20.0) * 60)
			)
		);
		// set the model matrix
		model_matrix.Set(
			ModelMatrixf::RotationX(FullCircles(time * 0.25))
		);

		gl.PolygonMode(PolygonMode::Line);
		gl.CullFace(Face::Front);
		torus_instr.Draw(torus_indices);
		//
		gl.PolygonMode(PolygonMode::Fill);
		gl.CullFace(Face::Back);
		torus_instr.Draw(torus_indices);
	}
예제 #4
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();
		//
		camera_matrix.Set(
			CamMatrixf::Orbiting(
				Vec3f(),
				3.0f,
				Degrees(time * 50),
				Degrees(SineWave(time / 16.0) * 80)
			)
		);
		// the model matrix
		model_matrix.Set(
			ModelMatrixf::RotationY(Degrees(time * 25))
		);
		// draw 36 instances of the cube
		// first the back faces
		gl.CullFace(Face::Front);
		front_facing.Set(0);
		cube_instr.Draw(cube_indices, inst_count);
		// then the front faces
		gl.CullFace(Face::Back);
		front_facing.Set(1);
		cube_instr.Draw(cube_indices, inst_count);
	}
예제 #5
0
int main(int argc,char** argv) {
	cout << "Hello Lord Firal" << endl;
	int i;
	// create program state
	ProgramState* state = new ProgramState();
	state->setRunning(true);
	// read in flags
	while((i=getopt(argc,argv,"tu:")) != EOF) {
		switch(i) {
			case 'u': {
				state->setRunning(false);
				break;
			}
			case 'l': {
				// load in the parameter
				break;
			}
			default:
				break;
		}
	}
	// process flags
	// run the program
	if(state->getRunning()) {
		Lazy* program = new Lazy(state);
		program->run();
		delete program;
	}
	return 0;
}
예제 #6
0
 void Reshape(GLuint width, GLuint height) {
     gl.Viewport(width, height);
     auto projection =
       CamMatrixf::PerspectiveX(Degrees(70), float(width) / height, 1, 200);
     sky_box_projection_matrix.Set(projection);
     shape_projection_matrix.Set(projection);
 }
예제 #7
0
 void Reshape(GLuint width, GLuint height) {
     gl.Viewport(width, height);
     Mat4f projection =
       CamMatrixf::PerspectiveX(Degrees(70), float(width) / height, 1, 40);
     shape_projection_matrix.Set(projection);
     plane_projection_matrix.Set(projection);
     halo_projection_matrix.Set(projection);
 }
예제 #8
0
TEST(Lazy, constUsage) {
	bool lambdaCalled = false;
	const Lazy<Foo> lazy([&lambdaCalled] { lambdaCalled = true; return Foo(42); });
	EXPECT_FALSE(lambdaCalled);
	EXPECT_FALSE(static_cast<bool>(lazy));
	EXPECT_EQ(42, (*lazy).value);
	EXPECT_EQ(42, lazy.value().value);
	EXPECT_EQ(42, lazy->value);
	EXPECT_TRUE(lambdaCalled);
	EXPECT_TRUE(static_cast<bool>(lazy));
}
예제 #9
0
const Metadata *
swift::_searchConformancesByMangledTypeName(const llvm::StringRef typeName) {
  auto &C = Conformances.get();
  const Metadata *foundMetadata = nullptr;

  pthread_mutex_lock(&C.SectionsToScanLock);

  unsigned sectionIdx = 0;
  unsigned endSectionIdx = C.SectionsToScan.size();

  for (; sectionIdx < endSectionIdx; ++sectionIdx) {
    auto &section = C.SectionsToScan[sectionIdx];
    for (const auto &record : section) {
      if (auto metadata = record.getCanonicalTypeMetadata())
        foundMetadata = _matchMetadataByMangledTypeName(typeName, metadata, nullptr);
      else if (auto pattern = record.getGenericPattern())
        foundMetadata = _matchMetadataByMangledTypeName(typeName, nullptr, pattern);

      if (foundMetadata != nullptr)
        break;
    }
    if (foundMetadata != nullptr)
      break;
  }

  pthread_mutex_unlock(&C.SectionsToScanLock);

  return foundMetadata;
}
예제 #10
0
static const TypeContextDescriptor *
_findNominalTypeDescriptor(Demangle::NodePointer node) {
  const TypeContextDescriptor *foundNominal = nullptr;
  auto &T = TypeMetadataRecords.get();

  auto mangledName = Demangle::mangleNode(node);

  // Look for an existing entry.
  // Find the bucket for the metadata entry.
  if (auto Value = T.NominalCache.find(mangledName))
    return Value->getDescription();

  // Check type metadata records
  T.SectionsToScanLock.withLock([&] {
    foundNominal = _searchTypeMetadataRecords(T, node);
  });

  // Check protocol conformances table. Note that this has no support for
  // resolving generic types yet.
  if (!foundNominal)
    foundNominal = _searchConformancesByMangledTypeName(node);

  if (foundNominal) {
    T.NominalCache.getOrInsert(mangledName, foundNominal);
  }

  return foundNominal;
}
예제 #11
0
const Metadata *
swift::_searchConformancesByMangledTypeName(const llvm::StringRef typeName) {
  auto &C = Conformances.get();
  const Metadata *foundMetadata = nullptr;

  ScopedLock guard(C.SectionsToScanLock);

  unsigned sectionIdx = 0;
  unsigned endSectionIdx = C.SectionsToScan.size();

  for (; sectionIdx < endSectionIdx; ++sectionIdx) {
    auto &section = C.SectionsToScan[sectionIdx];
    for (const auto &record : section) {
      if (auto metadata = record.getCanonicalTypeMetadata())
        foundMetadata = _matchMetadataByMangledTypeName(typeName, metadata, nullptr);
      else if (auto ntd = record.getNominalTypeDescriptor())
        foundMetadata = _matchMetadataByMangledTypeName(typeName, nullptr, ntd);

      if (foundMetadata != nullptr)
        break;
    }
    if (foundMetadata != nullptr)
      break;
  }

  return foundMetadata;
}
예제 #12
0
/// Search the witness table in the ConformanceCache. \returns a pair of the
/// WitnessTable pointer and a boolean value True if a definitive value is
/// found. \returns false if the type or its superclasses were not found in
/// the cache.
static
std::pair<const WitnessTable *, bool>
searchInConformanceCache(const Metadata *type,
                         const ProtocolDescriptor *protocol,
                         ConformanceCacheEntry *&foundEntry) {
  auto &C = Conformances.get();
  auto origType = type;

  foundEntry = nullptr;

recur_inside_cache_lock:

  // See if we have a cached conformance. Try the specific type first.

  {
    // Check if the type-protocol entry exists in the cache entry that we found.
    if (auto *Value = C.findCached(type, protocol)) {
      if (Value->isSuccessful())
        return std::make_pair(Value->getWitnessTable(), true);

      // If we're still looking up for the original type, remember that
      // we found an exact match.
      if (type == origType)
        foundEntry = Value;

      // If we got a cached negative response, check the generation number.
      if (Value->getFailureGeneration() == C.SectionsToScan.size()) {
        // We found an entry with a negative value.
        return std::make_pair(nullptr, true);
      }
    }
  }

  {
    // For generic and resilient types, nondependent conformances
    // are keyed by the nominal type descriptor rather than the
    // metadata, so try that.
    auto *description = type->getNominalTypeDescriptor().get();

    // Hash and lookup the type-protocol pair in the cache.
    if (auto *Value = C.findCached(description, protocol)) {
      if (Value->isSuccessful())
        return std::make_pair(Value->getWitnessTable(), true);

      // We don't try to cache negative responses for generic
      // patterns.
    }
  }

  // If the type is a class, try its superclass.
  if (const ClassMetadata *classType = type->getClassObject()) {
    if (classHasSuperclass(classType)) {
      type = swift_getObjCClassMetadata(classType->SuperClass);
      goto recur_inside_cache_lock;
    }
  }

  // We did not find an entry.
  return std::make_pair(nullptr, false);
}
예제 #13
0
	void Reshape(GLuint width, GLuint height)
	{
		gl.Viewport(width, height);
		projection_matrix.Set(
			CamMatrixf::PerspectiveX(
				Degrees(70),
				width, height,
				1, 100
			)
		);
	}
예제 #14
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();
		//
		// set the matrix for camera orbiting the origin
		camera_matrix.Set(
			CamMatrixf::Orbiting(
				Vec3f(),
				3.5,
				Degrees(time * 35),
				Degrees(SineWave(time / 60.0) * 80)
			)
		);
		// set the model matrix
		model_matrix.Set(
			ModelMatrixf::RotationX(FullCircles(time * 0.25))
		);

		torus_instr.Draw(torus_indices);
	}
예제 #15
0
	void Reshape(GLuint width, GLuint height)
	{
		gl.Viewport(width, height);
		prog.Use();
		projection_matrix.Set(
			CamMatrixf::PerspectiveX(
				Degrees(70),
				double(width)/height,
				1, 20
			)
		);
	}
예제 #16
0
    void Render(double time) {
        const double day_duration = 67.0;
        auto sun =
          Vec3f(0.000, 1.000, 0.000) * 1e10 * SineWave(time / day_duration) +
          Vec3f(0.000, 0.000, -1.000) * 1e10 * CosineWave(time / day_duration);

        auto camera = CamMatrixf::Orbiting(
          Vec3f(),
          5.0,
          FullCircles(-0.10 - time / 27.0),
          Degrees(-20 - SineWave(time / 17.0) * 30));

        auto model = ModelMatrixf::RotationA(
          Vec3f(1.0, 1.0, 1.0), FullCircles(time / 13.0));

        gl.Clear().ColorBuffer().DepthBuffer();

        sky_box.Use();
        sky_box_prog.Use();
        sky_box_camera_matrix.Set(camera);
        sky_box_sun_position.Set(sun);
        sky_box.Draw();

        shape.Use();
        shape_prog.Use();
        shape_model_matrix.Set(model);
        shape_camera_matrix.Set(camera);
        shape_camera_position.Set(camera.Position());
        shape_sun_position.Set(sun);
        shape.Draw();
    }
예제 #17
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();

		auto camera = CamMatrixf::Orbiting(
			Vec3f(),
			8.5,
			FullCircles(time / 5.0),
			Degrees(15 + (-SineWave(time/10.0)+1.0)* 0.5 * 75)
		);
		ModelMatrixf model =
			ModelMatrixf::Translation(0.0f, 2.5f, 0.0) *
			ModelMatrixf::RotationA(
				Vec3f(1.0f, 1.0f, 1.0f),
				FullCircles(time / 7.0)
			);

		plane_prog.Use();
		plane_camera_matrix.Set(camera);

		plane.Bind();
		gl.DrawArrays(PrimitiveType::TriangleStrip, 0, 4);

		shape_prog.Use();
		shape_camera_matrix.Set(camera);

		shape_model_matrix.Set(model);
		shape.Bind();
		shape_instr.Draw(shape_indices);

		halo_prog.Use();
		halo_camera_matrix.Set(camera);
		halo_model_matrix.Set(model);

		gl.DepthMask(false);
		gl.Enable(Capability::Blend);
		shape_instr.Draw(shape_indices);
		gl.Disable(Capability::Blend);
		gl.DepthMask(true);
	}
예제 #18
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();
		//
		Vec3f lightPos(-1.0f, 2.0f, 2.0f);
		lightPos *= (1.0f - SineWave(time/5.0f)*0.4f);
		light_pos.Set(lightPos);

		tex_projection_matrix.Set(
			CamMatrixf::PerspectiveX(Degrees(15), 1.0, 1, 20) *
			CamMatrixf::LookingAt(lightPos, Vec3f())
		);

		// set the model matrix
		model_matrix.Set(
			ModelMatrixf::RotationY(FullCircles(time * 0.1))
		);

		cube.Bind();
		gl.CullFace(Face::Front);
		cube_instr.Draw(cube_indices);
	}
예제 #19
0
	void Render(double time)
	{
		gl.Clear().ColorBuffer().DepthBuffer();

		camera_matrix.Set(
			CamMatrixf::Orbiting(
				Vec3f(),
				GLfloat(30.0 - SineWave(time / 17.0)*25.0),
				Degrees(time * 47),
				Degrees(SineWave(time / 31.0) * 90)
			)
		);

		gl.DrawArrays(PrimitiveType::Patches, 0, 16);
	}
예제 #20
0
static void _addImageTypeMetadataRecordsBlock(const uint8_t *records,
                                              size_t recordsSize) {
  assert(recordsSize % sizeof(TypeMetadataRecord) == 0
         && "weird-sized type metadata section?!");

  // If we have a section, enqueue the type metadata for lookup.
  auto recordsBegin
    = reinterpret_cast<const TypeMetadataRecord*>(records);
  auto recordsEnd
    = reinterpret_cast<const TypeMetadataRecord*>
                                            (records + recordsSize);

  // type metadata cache should always be sufficiently initialized by this point.
  _registerTypeMetadataRecords(TypeMetadataRecords.unsafeGetAlreadyInitialized(),
                               recordsBegin, recordsEnd);
}
예제 #21
0
static void _addImageProtocolConformancesBlock(const uint8_t *conformances,
                                               size_t conformancesSize) {
  assert(conformancesSize % sizeof(ProtocolConformanceRecord) == 0
         && "weird-sized conformances section?!");

  // If we have a section, enqueue the conformances for lookup.
  auto recordsBegin
    = reinterpret_cast<const ProtocolConformanceRecord*>(conformances);
  auto recordsEnd
    = reinterpret_cast<const ProtocolConformanceRecord*>
                                            (conformances + conformancesSize);
  
  // Conformance cache should always be sufficiently initialized by this point.
  _registerProtocolConformances(Conformances.unsafeGetAlreadyInitialized(),
                                recordsBegin, recordsEnd);
}
예제 #22
0
void swift::addImageTypeMetadataRecordBlockCallback(const void *records,
                                                    uintptr_t recordsSize) {
  assert(recordsSize % sizeof(TypeMetadataRecord) == 0
         && "weird-sized type metadata section?!");

  // If we have a section, enqueue the type metadata for lookup.
  auto recordBytes = reinterpret_cast<const char *>(records);
  auto recordsBegin
    = reinterpret_cast<const TypeMetadataRecord*>(records);
  auto recordsEnd
    = reinterpret_cast<const TypeMetadataRecord*>(recordBytes + recordsSize);

  // Type metadata cache should always be sufficiently initialized by this
  // point. Attempting to go through get() may also lead to an infinite loop,
  // since we register records during the initialization of
  // TypeMetadataRecords.
  _registerTypeMetadataRecords(TypeMetadataRecords.unsafeGetAlreadyInitialized(),
                               recordsBegin, recordsEnd);
}
예제 #23
0
static const TypeContextDescriptor *
_findNominalTypeDescriptor(Demangle::NodePointer node,
                           Demangle::Demangler &Dem) {
  const TypeContextDescriptor *foundNominal = nullptr;
  auto &T = TypeMetadataRecords.get();

  // If we have a symbolic reference to a context, resolve it immediately.
  NodePointer symbolicNode = node;
  if (symbolicNode->getKind() == Node::Kind::Type)
    symbolicNode = symbolicNode->getChild(0);
  if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
    return cast<TypeContextDescriptor>(
      (const ContextDescriptor *)symbolicNode->getIndex());

  auto mangledName =
    Demangle::mangleNode(node,
                         [&](const void *context) -> NodePointer {
                           return _buildDemanglingForContext(
                               (const ContextDescriptor *) context,
                               {}, false, Dem);
                         });

  // Look for an existing entry.
  // Find the bucket for the metadata entry.
  if (auto Value = T.NominalCache.find(mangledName))
    return Value->getDescription();

  // Check type metadata records
  foundNominal = _searchTypeMetadataRecords(T, node);

  // Check protocol conformances table. Note that this has no support for
  // resolving generic types yet.
  if (!foundNominal)
    foundNominal = _searchConformancesByMangledTypeName(node);

  if (foundNominal) {
    T.NominalCache.getOrInsert(mangledName, foundNominal);
  }

  return foundNominal;
}
예제 #24
0
static const Metadata *
_typeByMangledName(const llvm::StringRef typeName) {
  const Metadata *foundMetadata = nullptr;
  auto &T = TypeMetadataRecords.get();

  // Look for an existing entry.
  // Find the bucket for the metadata entry.
  if (auto Value = T.Cache.find(typeName))
    return Value->getMetadata();

  // Check type metadata records
  pthread_mutex_lock(&T.SectionsToScanLock);
  foundMetadata = _searchTypeMetadataRecords(T, typeName);
  pthread_mutex_unlock(&T.SectionsToScanLock);

  // Check protocol conformances table. Note that this has no support for
  // resolving generic types yet.
  if (!foundMetadata)
    foundMetadata = _searchConformancesByMangledTypeName(typeName);

  if (foundMetadata) {
    T.Cache.getOrInsert(typeName, foundMetadata);
  }

#if SWIFT_OBJC_INTEROP
  // Check for ObjC class
  // FIXME does this have any value? any ObjC class with a Swift name
  // should already be registered as a Swift type.
  if (foundMetadata == nullptr) {
    std::string prefixedName("_Tt" + typeName.str());
    foundMetadata = reinterpret_cast<ClassMetadata *>
      (objc_lookUpClass(prefixedName.c_str()));
  }
#endif

  return foundMetadata;
}
예제 #25
0
static BoxPair::Return _swift_allocBox_(const Metadata *type) {
  // Get the heap metadata for the box.
  auto &B = Boxes.get();
  const void *typeArg = type;
  auto entry = B.findOrAdd(&typeArg, 1, [&]() -> BoxCacheEntry* {
    // Create a new entry for the box.
    auto entry = BoxCacheEntry::allocate(B.getAllocator(), &typeArg, 1, 0);

    auto metadata = entry->getData();
    metadata->Offset = GenericBoxHeapMetadata::getHeaderOffset(type);
    metadata->BoxedType = type;

    return entry;
  });

  auto metadata = entry->getData();

  // Allocate and project the box.
  auto allocation = swift_allocObject(metadata, metadata->getAllocSize(),
                                      metadata->getAllocAlignMask());
  auto projection = metadata->project(allocation);

  return BoxPair{allocation, projection};
}
예제 #26
0
void
swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
                                         const TypeMetadataRecord *end) {
  auto &T = TypeMetadataRecords.get();
  _registerTypeMetadataRecords(T, begin, end);
}
예제 #27
0
 Laziness()
 : total([&]{ return first.get()+ second.get(); }, total.depends(first).depends(second))
 {}
예제 #28
0
const WitnessTable *
swift::swift_conformsToProtocol(const Metadata *type,
                                const ProtocolDescriptor *protocol) {
  auto &C = Conformances.get();
  auto origType = type;
  unsigned numSections = 0;
  ConformanceCacheEntry *foundEntry;

recur:
  // See if we have a cached conformance. The ConcurrentMap data structure
  // allows us to insert and search the map concurrently without locking.
  // We do lock the slow path because the SectionsToScan data structure is not
  // concurrent.
  auto FoundConformance = searchInConformanceCache(type, protocol, foundEntry);
  // The negative answer does not always mean that there is no conformance,
  // unless it is an exact match on the type. If it is not an exact match,
  // it may mean that all of the superclasses do not have this conformance,
  // but the actual type may still have this conformance.
  if (FoundConformance.second) {
    if (FoundConformance.first || foundEntry)
      return FoundConformance.first;
  }

  // If we didn't have an up-to-date cache entry, scan the conformance records.
  C.SectionsToScanLock.lock();
  unsigned failedGeneration = ConformanceCacheGeneration;

  // If we have no new information to pull in (and nobody else pulled in
  // new information while we waited on the lock), we're done.
  if (C.SectionsToScan.size() == numSections) {
    if (failedGeneration != ConformanceCacheGeneration) {
      // Someone else pulled in new conformances while we were waiting.
      // Start over with our newly-populated cache.
      C.SectionsToScanLock.unlock();
      type = origType;
      goto recur;
    }


    // Save the failure for this type-protocol pair in the cache.
    C.cacheFailure(type, protocol);

    C.SectionsToScanLock.unlock();
    return nullptr;
  }

  // Update the last known number of sections to scan.
  numSections = C.SectionsToScan.size();

  // Scan only sections that were not scanned yet.
  unsigned sectionIdx = foundEntry ? foundEntry->getFailureGeneration() : 0;
  unsigned endSectionIdx = C.SectionsToScan.size();

  for (; sectionIdx < endSectionIdx; ++sectionIdx) {
    auto &section = C.SectionsToScan[sectionIdx];
    // Eagerly pull records for nondependent witnesses into our cache.
    for (const auto &record : section) {
      // If the record applies to a specific type, cache it.
      if (auto metadata = record.getCanonicalTypeMetadata()) {
        auto P = record.getProtocol();

        // Look for an exact match.
        if (protocol != P)
          continue;

        if (!isRelatedType(type, metadata, /*isMetadata=*/true))
          continue;

        // Store the type-protocol pair in the cache.
        auto witness = record.getWitnessTable(metadata);
        if (witness) {
          C.cacheSuccess(metadata, P, witness);
        } else {
          C.cacheFailure(metadata, P);
        }

      // If the record provides a nondependent witness table for all instances
      // of a generic type, cache it for the generic pattern.
      // TODO: "Nondependent witness table" probably deserves its own flag.
      // An accessor function might still be necessary even if the witness table
      // can be shared.
      } else if (record.getTypeKind()
                   == TypeMetadataRecordKind::UniqueNominalTypeDescriptor
                 && record.getConformanceKind()
                   == ProtocolConformanceReferenceKind::WitnessTable) {

        auto R = record.getNominalTypeDescriptor();
        auto P = record.getProtocol();

        // Look for an exact match.
        if (protocol != P)
          continue;

        if (!isRelatedType(type, R, /*isMetadata=*/false))
          continue;

        // Store the type-protocol pair in the cache.
        C.cacheSuccess(R, P, record.getStaticWitnessTable());
      }
    }
  }
  ++ConformanceCacheGeneration;

  C.SectionsToScanLock.unlock();
  // Start over with our newly-populated cache.
  type = origType;
  goto recur;
}
예제 #29
0
void
swift::swift_registerProtocolConformances(const ProtocolConformanceRecord *begin,
                                          const ProtocolConformanceRecord *end){
  auto &C = Conformances.get();
  _registerProtocolConformances(C, begin, end);
}
예제 #30
0
/// Search the witness table in the ConformanceCache. \returns a pair of the
/// WitnessTable pointer and a boolean value True if a definitive value is
/// found. \returns false if the type or its superclasses were not found in
/// the cache.
static
std::pair<const WitnessTable *, bool>
searchInConformanceCache(const Metadata *type,
                         const ProtocolDescriptor *protocol,
                         ConformanceCacheEntry *&foundEntry) {
  auto &C = Conformances.get();
  auto origType = type;

  foundEntry = nullptr;

recur_inside_cache_lock:

  // See if we have a cached conformance. Try the specific type first.

  // Hash and lookup the type-protocol pair in the cache.
  size_t hash = hashTypeProtocolPair(type, protocol);
  ConcurrentList<ConformanceCacheEntry> &Bucket =
    C.Cache.findOrAllocateNode(hash);

  // Check if the type-protocol entry exists in the cache entry that we found.
  for (auto &Entry : Bucket) {
    if (!Entry.matches(type, protocol)) continue;

    if (Entry.isSuccessful()) {
      return std::make_pair(Entry.getWitnessTable(), true);
    }

    if (type == origType)
      foundEntry = &Entry;

    // If we got a cached negative response, check the generation number.
    if (Entry.getFailureGeneration() == C.SectionsToScan.size()) {
      // We found an entry with a negative value.
      return std::make_pair(nullptr, true);
    }
  }

  // If the type is generic, see if there's a shared nondependent witness table
  // for its instances.
  if (auto generic = type->getGenericPattern()) {
    // Hash and lookup the type-protocol pair in the cache.
    size_t hash = hashTypeProtocolPair(generic, protocol);
    ConcurrentList<ConformanceCacheEntry> &Bucket =
      C.Cache.findOrAllocateNode(hash);

    for (auto &Entry : Bucket) {
      if (!Entry.matches(generic, protocol)) continue;
      if (Entry.isSuccessful()) {
        return std::make_pair(Entry.getWitnessTable(), true);
      }
      // We don't try to cache negative responses for generic
      // patterns.
    }
  }

  // If the type is a class, try its superclass.
  if (const ClassMetadata *classType = type->getClassObject()) {
    if (classHasSuperclass(classType)) {
      type = swift_getObjCClassMetadata(classType->SuperClass);
      goto recur_inside_cache_lock;
    }
  }

  // We did not find an entry.
  return std::make_pair(nullptr, false);
}